Oracle 索引的维护
一.查看系統表中的用戶索引
在Oracle中,SYSTEM表是安裝數據庫時自動建立的,它包含數據庫的全部數據字典,存儲過程、包、函數和觸發器的定義以及系統回滾段。
一般來說,應該盡量避免在SYSTEM表中存儲非SYSTEM用戶的對象。因為這樣會帶來數據庫維護和管理的很多問題。一旦SYSTEM表損壞了,只能重新生成數據庫。我們可以用下面的語句來檢查在SYSTEM表內有沒有其他用戶的索引存在。
/*?Formatted?on?2010/6/19?13:22:46?(QP5?v5.115.810.9015)?*/
SELECT???*
??FROM???dba_indexes
?WHERE???tablespace_name?=?'SYSTEM'?AND?owner?NOT?IN?('SYS',?'SYSTEM')
二.?索引的存儲情況檢查
Oracle為數據庫中的所有數據分配邏輯結構空間。數據庫空間的單位是block、extent和segment。
Block:是Oracle使用和分配的最小存儲單位。它是由數據庫建立時設置的DB_BLOCK_SIZE決定的。一旦數據庫生成了,數據塊的大小不能改變。要想改變只能重新建立數據庫。
Extent:是由一組連續的block組成的。一個或多個extent組成一個segment。當一個segment中的所有空間被用完時,Oracle為它分配一個新的extent。
Segment:是由一個或多個extent組成的。它包含某表空間中特定邏輯存儲結構的所有數據。一個段中的extent可以是不連續的,甚至可以在不同的數據文件中。
可以參考:
表空間(tableSpace)?段(segment)?盤區(extent)?塊(block)?關系?
http://blog.csdn.net/tianlesoftware/archive/2009/12/13/4962476.aspx
一個object只能對應于一個邏輯存儲的segment,我們通過查看該segment中的extent,可以看出相應object的存儲情況。
(1)查看索引段中extent的數量:
/*?Formatted?on?2010/6/19?13:47:34?(QP5?v5.115.810.9015)?*/
??SELECT???segment_name,?COUNT?(?*?)
????FROM???dba_extents
???WHERE???segment_type?=?'INDEX'?AND?owner?=?UPPER?('NEWCCS')
????GROUP?BY???segment_name
(2)查看表空間內的索引的擴展情況:
/*?Formatted?on?2010/6/19?14:05:23?(QP5?v5.115.810.9015)?*/
??SELECT???SUBSTR?(segment_name,?1,?20)?"SEGMENT?NAME",?bytes,?COUNT?(bytes)
????FROM???dba_extents
???WHERE???segment_name?IN?(SELECT???index_name
??????????????????????????????FROM???dba_indexes
?????????????????????????????WHERE???tablespace_name?=?UPPER?('NEWCCS'))
GROUP?BY???segment_name,?bytes
ORDER?BY???segment_name
三.?索引的選擇性
索引的選擇性是指索引列中不同值的數目與表中記錄數的比。如果一個表中有2000條記錄,表索引列有1980個不同的值,那么這個索引的選擇性就是1980/2000=0.99。一個索引的選擇性越接近于1,這個索引的效率就越高。
如果是使用基于cost的最優化,優化器不應該使用選擇性不好的索引。如果是使用基于rule的最優化,優化器在確定執行路徑時不會考慮索引的選擇性(除非是唯一性索引),并且不得不手工優化查詢以避免使用非選擇性的索引。
確定索引的選擇性,可以有兩種方法:手工測量?和?自動測量。
(1)手工測量索引的選擇性
如果要根據一個表的兩列創建兩列并置索引,可以用以下方法測量索引的選擇性:
列的選擇性=不同值的數目/行的總數??/*?越接近1越好?*/
select?count(distinct?第一列||"%"||第二列)/count(*)??from??表名
如果我們知道其中一列索引的選擇性(例如其中一列是主鍵),那么我們就可以知道另一列索引的選擇性。
手工方法的優點是在創建索引前就能評估索引的選擇性。
(2)自動測量索引的選擇性
如果分析一個表,也會自動分析所有表的索引。
第一,為了確定一個表的確定性,就要分析表。
analyze?table?表名?compute?statistics
第二,確定索引里不同關鍵字的數目:
select?distinct_keys?from?user_indexes?where?table_name="表名"?and?index_name="索引名"
第三,確定表中行的總數:
select?num_rows?from?user_tables?where?table_name="表名"
第四,索引的選擇性=索引里不同關鍵字的數目/表中行的總數:
select?i.distinct_keys/t.num_rows?from?user_indexes?i,??user_tables?t?
?????where?i.table_name="表名"?and?i.index_name="索引名"?and?i.table_name=t.table_name
第五,可以查詢USER_TAB_COLUMNS以了解每個列的選擇性。
????表中所有行在該列的不同值的數目:
????select?column_name,?num_distinct?from?user_tab_columns?where?table_name="表名"
列的選擇性=NUM_DISTINCT/表中所有行的總數,查詢USER_TAB_COLUMNS有助測量每個列的選擇性,但它并不能精確地測量列的并置組合的選擇性。要想測量一組列的選擇性,需要采用手工方法或者根據這組列創建一個索引并重新分析表。
四.?確定索引的實際碎片
隨著數據庫的使用,不可避免地對基本表進行插入,更新和刪除,這樣導致葉子行在索引中被刪除,使該索引產生碎片。插入刪除越頻繁的表,索引碎片的程度也越高。碎片的產生使訪問和使用該索引的I/O成本增加。碎片較高的索引必須重建以保持最佳性能。
(1)利用驗證索引命令對索引進行驗證。
這將有價值的索引信息填入index_stats表。
validate?index?用戶名.索引名
或者:
analyze?index?index_name?validate?structure;
注意:index_stats只保存最近一次分析的結果
(2)查詢index_stats表以確定索引中刪除的、未填滿的葉子(Leaf)行的百分比?和?height?字段。?
select?name,height,?del_lf_rows,?lf_rows,?round((del_lf_rows/(lf_rows+0.0000000001))*100)?"Frag?Percent"?from?index_stats
(3)如果索引的葉子行的碎片超過10%,或者?index_stats中height?>?=4,?可以考慮對索引進行重建。
alter?index?用戶名.索引名?rebuild??tablespace?表空間名??storage(initial?初始值?next?擴展值)??nologging
參考:如何加快建?index?索引?的時間
http://blog.csdn.net/tianlesoftware/archive/2010/06/11/5664019.aspx
DBA1群里?長沙-Rourk33?同學提供的腳本,?可以一次生成擴展大于10次的索引的腳本。感謝Rourk33?同學。
/*?Formatted?on?2010/6/19?21:58:45?(QP5?v5.115.810.9015)?*/
SELECT???'alter?index?'?||?owner?||?'.'?||?segment_name?||?'?rebuild;'
??FROM???(??SELECT???COUNT?(?*?),
?????????????????????owner,
?????????????????????segment_name,
?????????????????????t.tablespace_name
??????????????FROM???dba_extents?t
?????????????WHERE???t.segment_type?=?'INDEX'
?????????????????????AND?t.owner?NOT?IN?('SYS',?'SYSTEM')
??????????GROUP?BY???owner,?segment_name,?t.tablespace_name
????????????HAVING???COUNT?(?*?)?>?10
??????????ORDER?BY???COUNT?(?*?)?DESC);
(4)如果出于空間或其他考慮,不能重建索引,可以整理索引。
?alter?index用戶名.索引名?coalesce
(5)清除分析信息
???analyze?index?用戶名.索引名?delete?statistics
五.?重建索引
(1)檢查需要重建的索引
根據以下幾方面進行檢查,確定需要重建的索引。
第一,查看SYSTEM表空間中的用戶索引
為了避免數據字典的碎片出現,要盡量避免在SYSTEM表空間出現用戶的表和索引。
select?index_name?from?dba_indexes?where?tablespace_name="SYSTEM"?and?owner?not?in?("SYS","SYSTEM")
第二,確保用戶的表和索引不在同一表空間內
表和索引對象的第一個規則是把表和索引分離。把表和相應的索引建立在不同的表空間中,最好在不同的磁盤上。這樣可以避免在數據管理和查詢時出現的許多I/O沖突。
/*?Formatted?on?2010/6/19?21:00:08?(QP5?v5.115.810.9015)?*/
SELECT???i.owner?"OWNER",
?????????i.index_name?"INDEX",
?????????t.table_name?"TABLE",
?????????i.tablespace_name?"TABLESPACE"
??FROM???dba_indexes?i,?dba_tables?t
?WHERE???????i.owner?=?t.owner
?????????AND?i.table_name?=?t.table_name
?????????AND?i.tablespace_name?=?t.tablespace_name
?????????AND?i.owner?NOT?IN?('SYS',?'SYSTEM')
第三,查看數據表空間里有哪些索引
用戶的默認表空間應該不是SYSTEM表空間,而是數據表空間。在建立索引時,如果不指定相應的索引表空間名,那么,該索引就會建立在數據表空間中。這是程序員經常忽略的一個問題。應該在建索引時,明確的指明相應的索引表空間。
/*?Formatted?on?2010/6/19?21:05:01?(QP5?v5.115.810.9015)?*/
??SELECT???owner,?segment_name,?SUM?(bytes)
????FROM???dba_segments
???WHERE???tablespace_name?='SYSTEM'?AND?segment_type?=?'INDEX'
GROUP?BY???owner,?segment_name
第四,查看哪個索引被擴展了超過10次
隨著表記錄的增加,相應的索引也要增加。如果一個索引的next?extent值設置不合理(太小),索引段的擴展變得很頻繁。索引的extent太多,檢索時的速度和效率就會降低。
(1)?查看索引擴展次數
/*?Formatted?on?2010/6/19?21:13:41?(QP5?v5.115.810.9015)?*/
??SELECT???COUNT?(?*?),
???????????owner,
???????????segment_name,
???????????tablespace_name
????FROM???dba_extents
???WHERE???segment_type?=?'INDEX'?AND?owner?NOT?IN?('SYS',?'SYSTEM')
GROUP?BY???owner,?segment_name,?tablespace_name
??HAVING???COUNT?(?*?)?>?10
ORDER?BY???COUNT?(?*?)?DESC
(2)找出需要重建的索引后,需要確定索引的大小,以設置合理的索引存儲參數。
/*?Formatted?on?2010/6/19?21:19:32?(QP5?v5.115.810.9015)?*/
??SELECT???owner?"OWNER",
???????????segment_name?"INDEX",
???????????tablespace_name?"TABLESPACE",
???????????bytes?"BYTES/COUNT",
???????????SUM?(bytes)?"TOTAL?BYTES",
???????????ROUND?(SUM?(bytes)?/?(1024?*?1024),?0)?"TOTAL?M",
???????????COUNT?(bytes)?"TOTAL?COUNT"
????FROM???dba_extents
???WHERE???segment_type?=?'INDEX'
???????????AND?segment_name?IN?('INDEX_NAME1',?'INDEX_NAME2')
GROUP?BY???owner,
???????????segment_name,
???????????segment_type,
???????????tablespace_name,
???????????bytes
ORDER?BY???owner,?segment_name
(3)確定索引表空間還有足夠的剩余空間
確定要把索引重建到哪個索引表空間中。要保證相應的索引表空間有足夠的剩余空間。
/*?Formatted?on?2010/6/19?21:27:50?(QP5?v5.115.810.9015)?*/
SELECT???ROUND?(bytes?/?(1024?*?1024),?2)?"free(M)"
??FROM???sm$ts_free
?WHERE???tablespace_name?=?'表空間名'
(4)重建索引
重建索引時要注意以下幾點:
a.如果不指定tablespace名,索引將建在用戶的默認表空間。
b.如果不指定nologging,將會寫日志,導致速度變慢。由于索引的重建沒有恢復的必要,所以,可以不寫日志。
c.如果出現資源忙,表明有進程正在使用該索引,等待一會再提交。
alter?index?索引名?rebuild??tablespace?索引表空間名??storage(initial?初始值?next?擴展值)??nologging?
(5)檢查索引
對重建好的索引進行檢查。
select?*?from?dba_extents?where?segment_name="索引名"
(6)根據索引進行查詢,檢查索引是否有效
使用相應的where條件進行查詢,確保使用該索引。看看使用索引后的效果如何。
select?*?from?dba_ind_columns?where?index_name='索引名'
然后,根據相應的索引項進行查詢。
select?*?from?"表名"??where?...
(7)找出有碎片的表空間,并收集其碎片。
重建索引后,原有的索引被刪除,這樣會造成表空間的碎片。
/*?Formatted?on?2010/6/19?21:40:45?(QP5?v5.115.810.9015)?*/
SELECT???'alter?tablespace?'?||?tablespace_name?||?'?coalesce;'
??FROM???dba_free_space_coalesced
?WHERE???percent_blocks_coalesced?!=?100
?
?
查看索引占用空間大小:
select?(sum(bytes)/1024/1024)||'MB'?from?dba_segments?where?segment_name?=?'INDBILLLOG5_CALLEND';
查看表占用空間大小
select?(sum(bytes)/1024/1024)||'MB'?from?dba_segments?where?segment_name?=?'TBILLLOG5';
?
注: 整理自網絡
------------------------------------------------------------------------------?
Blog:?http://blog.csdn.net/tianlesoftware?
網上資源:?http://tianlesoftware.download.csdn.net?
相關視頻:http://blog.csdn.net/tianlesoftware/archive/2009/11/27/4886500.aspx?
DBA1?群:62697716(滿);?DBA2?群:62697977
整理表空間的碎片。
alter?tablespace?表空間名?coalesce
總結
以上是生活随笔為你收集整理的Oracle 索引的维护的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 梦到有病的亲人死了什么预兆
- 下一篇: 梦到把面条分给别人吃好不好