Oracle創建索引的基本規則

原帖地址:http://www.2cto.com/database/201305/211767.html

最近拜讀的一篇文章。

Oracle創建索引的基本規則
 
一、B-Tree索引
1.  選擇索引字段的原則:
在WHERE子句中最頻繁使用的字段  
 聯接語句中的聯接字段 
選擇高選擇性的字段(如果很少的字段擁有相同值,即有很多獨特值,則選擇性很好) 
Oracle在UNIQUE和主鍵字段上自動建立索引 
在選擇性很差的字段上建索引只有在這個字段的值分佈非常傾斜的情況下才有益(在這種情況下,某一,兩個字段值比其它字段值少出現很多) 
不要在很少獨特值的字段上建B-TREE索引,在這種情況下,你可以考慮在這些字段上建位圖索引.在聯機事務處理環境下,併發性非常高,索引經常被修改,所以不應該建位圖索引 
不要在經常被修改的字段上建索引.當有UPDATE,DELETE,INSETT操作時,ORACLE除了要更新表的數據外,同時也要更新索引,而且就象更新數據一樣,或產生還原和重做條目 
不要在有用到函數的字段上建索引,ORACLE在這種情況,優化器不會用到索引,除非你建立函數索引 
可以考慮在外鍵字段上建索引,這些索引允許當在主表上UPDATE,DELETE操作時,不需要共享子表的鎖,這非常適用於在父表和子表上有很多併發的INSERT,UPDATE和DELETE操作的情況 
當建立索引後,請比較一下索引後所獲得的查詢性能的提高和UPDATE,DELETE,INSERT操作性能上的損失,比較得失後,再最後決定是否需建立這個索引 
 2.  選擇建立複合索引
 複合索引的優點:
改善選擇性:複合索引比單個字段的索引更具選擇性  
 減少I/O:如果要查詢的字段剛好全部包含在複合索引的字段裏,則ORACLE只須訪問索引,無須訪問表 
什麼情況下優化器會用到複合索引呢?
       (a) 當SQL語句的WHERE子句中有用到複合索引的領導字段時,ORACLE優化器會考慮用到複合索引來訪問.
       (b) 當某幾個字段在SQL語句的WHERE子句中經常通過AND操作符聯合在一起使用作爲過濾謂詞,並且這幾個字段合在一起時選擇性比各自單個字段的選擇性要更好時,可
       能考慮用這幾個字段來建立複合索引.
       (c) 當有幾個查詢語句都是查詢同樣的幾個字段值時,則可以考慮在這幾個字段上建立複合索引.
複合索引字段排序的原則:
確保在WHERE子句中使用到的字段是複合索引的領導字段  
 如果某個字段在WHERE子句中最頻繁使用,則在建立複合索引時,考慮把這個字段排在第一位(在CREATE INDEX語句中)  
 如果所有的字段在WHERE子句中使用頻率相同,則將最具選擇性的字段排在最前面,將最不具選擇性的字段排在最後面  
 如果所有的字段在WHERE子句中使用頻率相同,如果數據在物理上是按某一個字段排序的,則考慮將這個字段放在複合索引的第一位 
二、位圖索引
什麼情況下位圖索引能夠改善查詢的性能呢?
WHERE子句包含多個謂詞於中低基數的字段  
 單個的謂詞在這些中低基數的字段上選取大量的行  
 已經有位圖索引創建於某些或全部的這些中低基數的字段上 
被查詢的表包含很多行 
可以在單一個表上建立多個位圖索引,因此,位圖索引能夠改善包含冗長WHERE子句的複雜查詢的性能,在合計查詢和星形模型的聯接查詢語句中,位圖索引也可以提供比較優良的性能
位圖索引與B-TREE索引的比較
位圖索引更節省存儲空間 
位圖索引比較適用於數據倉庫環境,但不適於聯機事務處理環境.在數據倉庫環境,數據維護通常上通過批量INSERT和批量UPDATE來完成的,所以索引的維護被延遲直到DML操作結束.舉例:當你批量插入1000行數據時,這些插入的行被放置到排序緩存中(SORT BUFFER),然後批處理更新這1000個索引條目,所以,每一個位圖段在每一個DML操作中只需更新一次,即使在那個位圖段裏有多行被更新 
一個鍵值的壓縮位圖是由一個或多個位圖段所組成,每一個位圖段大約相當於半個BLOCK SIZE那麼大,鎖的最小粒度是一個位圖段,在聯機事務處理環境,如果多個事務執行同時的更新(即併發的更新),使用位圖索引就會影響UPDATE,INSERT,DELETE性能了 
一個B-TREE索引的條目只包含一個ROWID,因此,當一個索引條目被鎖定,即一行被鎖定.但是對於位圖索引, 一個索引條目潛在地有可能包含一段ROWID(即某一個範圍內的ROWID,有多個ROWID),當一個位圖索引條目被鎖定時,則這個條目包含的那一段ROWID都被鎖定,從而影響併發性.當一個位圖段內的ROWID的數量越多時,併發性就越差.雖然如此,對於BULK INSERT,UPDATE和DELETE,位圖索引的性能還是比B-TREE索引要好.
三、索引和NULL
        NULL值在索引中是被看做一個獨特值的除非當一個索引的兩行或多行的NON-NULL值是相等的情況下.在那種情況下,行被看做是相等的,因此,唯一索引不允許行包含空值以怕被看做是相等的.但是,當所有的行都是空值時,這個規則就不適用.Oracle並不索引所有健值都爲NULL的表的行,除非是位圖索引或當主鍵字段值是NULL時
四、建立索引常用的規則如下
表的主鍵、外鍵必須有索引; 
數據量超過300的表應該有索引; 
經常與其他表進行連接的表,在連接字段上應該建立索引; 
經常出現在Where子句中的字段,特別是大表的字段,應該建立索引; 
索引應該建在選擇性高的字段上; 
索引應該建在小字段上,對於大的文本字段甚至超長字段,不要建索引; 
複合索引的建立需要進行仔細分析;儘量考慮用單字段索引代替: 
        A、正確選擇複合索引中的主列字段,一般是選擇性較好的字段;
        B、複合索引的幾個字段是否經常同時以AND方式出現在Where子句中?單字段查詢是否極少甚至沒有?如果是,則可以建立複合索引;否則考慮單字段索引;
        C、如果複合索引中包含的字段經常單獨出現在Where子句中,則分解爲多個單字段索引;
        D、如果複合索引所包含的字段超過3個,那麼仔細考慮其必要性,考慮減少複合的字段;
        E、如果既有單字段索引,又有這幾個字段上的複合索引,一般可以刪除複合索引;
頻繁進行數據操作的表,不要建立太多的索引; 
刪除無用的索引,避免對執行計劃造成負面影響; 
        以上是一些普遍的建立索引時的判斷依據。一言以蔽之,索引的建立必須慎重,對每個索引的必要性都應該經過仔細分析,要有建立的依據。因爲太多的索引與不充分、不正確的索引對性能都毫無益處:在表上建立的每個索引都會增加存儲開銷,索引對於插入、刪除、更新操作也會增加處理上的開銷。另外,過多的複合索引,在有單字段索引的情況下,一般都是沒有存在價值的;相反,還會降低數據增加刪除時的性能,特別是對頻繁更新的表來說,負面影響更大。
 
 
創建Oracle索引的7個注意事項
在創建Oracle索引時,有一些問題使我們需要注意的,下面就爲您介紹創建Oracle索引的一些注意事項,希望對您學習創建Oracle索引方面能有所幫助。
1、一般來說,不需要爲比較小的表創建索引;
2、即使是大表,如果經常需要查詢的數據不超過10%到15%的話,那就沒有必要爲其建立索引的必要。因爲此時建立索引的開銷可能要比性能的改善大的多。這個比例只是一個經驗的數據。如果數據庫管理員需要得出一個比較精確的結論,那麼就需要進行測試分析。
3、如對於一些重複內容比較少的列,特別是對於那些定義了唯一約束的列。在這些列上建立索引,往往可以起到非常不錯的效果。如對於一些null值的列與非Null值的列混合情況下,如果用戶需要經常查詢所有的非Null值記錄的列,則最好爲其設置索引。如果經常需要多表連接查詢,在用與連接的列上設置索引可以達到事半功倍的效果。
4、數據庫管理員,需要隔一段時間,如一年,對數據庫的索引進行優化。該去掉的去掉,該調整的調整,以提高數據庫的性能。
5、通常來說,表的索引越多,其查詢的速度也就越快。但是,表的更新速度則會降低。這主要是因爲表的更新(如往表中插入一條記錄)速度,反而隨着索引的增加而增加。這主要是因爲,在更新記錄的同時需要更新相關的索引信息。爲此,到底在表中創建多少索引合適,就需要在這個更新速度與查詢速度之間取得一個均衡點。
6、對於一些數據倉庫或者決策型數據庫系統,其主要用來進行查詢。相關的記錄往往是在數據庫初始化的時候倒入。此時,設置的索引多一點,可以提高數據庫的查詢性能。同時因爲記錄不怎麼更新,所以索引比較多的情況下,也不會影響到更新的速度。即使在起初的時候需要導入大量的數據,此時也可以先將索引禁用掉。等到數據導入完畢後,再啓用索引。可以通過這種方式來減少索引對數據更新的影響。相反,如果那些表中經常需要更新記錄,如一些事務型的應用系統,數據更新操作是家常便飯的事情。此時如果在一張表中建立過多的索引,則會影響到更新的速度。
7、關於位圖索引。
基數是位圖索引中的一個基本的定義,它是指數據庫表中某個字段內容中不重複的數值。如在員工信息表中的性別字段,一般就只有男跟女兩個值,所以,其基數爲2;婚姻狀況字段的話,則其只有已婚、未婚、離婚三種狀態,其基數就爲3;民族一覽內也是隻有有限的幾個值。
 
 
怎樣建立最佳索引?
 
1、明確地創建索引
create index index_name on table_name(field_name)
tablespace tablespace_name
pctfree 5
initrans 2
maxtrans 255
storage
(
minextents 1
maxextents 16382
pctincrease 0
);
 
2、創建基於函數的索引
常用與UPPER、LOWER、TO_CHAR(date)等函數分類上,例:
create index idx_func on emp(UPPER(ename)) tablespace tablespace_name;
 
3、創建位圖索引
對基數較小,且基數相對穩定的列建立索引時,首先應該考慮位圖索引,例:
create bitmap index idx_bitm on class (classno) tablespace tablespace_name;
 
4、明確地創建唯一索引
可以用create unique index語句來創建唯一索引,例:
create unique index dept_unique_idx on dept(dept_no) tablespace idx_1;
 
5、創建與約束相關的索引
可以用using index字句,爲與unique和primary key約束相關的索引,例:
alter table table_name
add constraint PK_primary_keyname primary key(field_name)
using index tablespace tablespace_name;
 
如何創建局部區索引?
1)基礎表必須是分區表
2)分區數量與基礎表相同
3)每個索引分區的子分區數量與相應的基礎表分區相同
4)基礎表的自分區中的行的索引項,被存儲在該索引的相應的自分區中,例如
create index TG_CDR04_SERV_ID_IDX on TG_CDR04(SERV_ID)
Pctfree 5
Tablespace TBS_AK01_IDX
Storage(
MaxExtents 32768
PctIncrease 0
FreeLists 1
FreeList Groups 1
)
local
/
 
如何創建範圍分區的全局索引?
基礎表可以是全局表和分區表
create index idx_start_date on tg_cdr01(start_date)
global partition by range(start_date)
(partition p01_idx vlaues less than ('0106')
partition p01_idx vlaues less than ('0111')
...
partition p01_idx vlaues less than ('0401'))
/
 
如何重建現存的索引?
重建現存的索引的當前時刻不會影響查詢
重建索引可以刪除額外的數據塊
提高索引查詢效率
alter index idx_name rebuild nologging;
對於分區索引
alter index idx_name rebuild partition partition_name nologging;
 
刪除索引的原因?
1)不再需要的索引
2)索引沒有針對其相關的表所發佈的查詢提供所期望的性能改善
3)應用沒有用該索引來查詢數據
4)該索引無效,必須在重建之前刪除該索引
5)該索引已經變的太碎了,必須在重建之前刪除該索引
語句:
drop index idx_name;
drop index idx_name partition partition_name;
 
建立索引的代價?
基礎表維護時,系統要同時維護索引,不合理的索引將嚴重影響系統資源,
主要表現在CPU和I/O上。
插入、更新、刪除數據產生大量db file sequential read鎖等待。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章