數據庫索引——索引列選擇以及空值問題


學習了園子里關於數據庫索引的一些文章,我也來摘抄一些關注度不高但對於理解索引概念以及掌握它的用法比較重要的一些知識點。不妥之處還望指正交流。


典型的基於索引的訪問路徑通常包含下面三步:
1、遍歷索引樹並在將SQL語句中的謂語應用到索引列后搜集葉子塊的行編號。
2、使用行編號從表數據塊中獲取數據行。
3、在所獲取的數據行上應用其余的謂語來得出最終結果集。
如果在第1步中返回了大量的行編號,第2步訪問表數據塊的代價就會更高,對於來自索引葉子塊的每一個行編號,都需要訪問表數據塊,並且這可能會導致多次物理I/O從而引起性能問題。


所以,選擇進行索引的最佳列對於提高SQL訪問性能是非常關鍵的。對於索引列的選擇應該與SQL語句中所使用的謂語相匹配,一般有以下需要考慮的內容:
1、如果應用代碼訪問某張表的時候在某一列上使用了等式或者范圍謂語,考慮對這一行進行索引就是一個很好的策略。對於多列索引,引導列應該是在大多數謂語中被使用的列。
2、考慮謂語的基數[1]以及列的選擇度[2]也是很重要的。例如,如果某個列只有兩個唯一值並且是均勻分布的,那么這一列可能就不適合建立B-樹索引,因為在這一列上使用等式謂語將會獲取50%的數據行。另一方面,如果這個列有兩個唯一值但不是均勻分布的,也就是說有一個值僅在很少的數據行中出現且應用使用這個不常出現的列值來訪問表,這種情況下最好在這一列上建立索引。
3、舉個例子:一張work-in-progress表上經過處理的具有3個唯一值(P、N和E)的Processed列。應用通過謂語Processed='N'來訪問這張表。在Processed列中僅有幾行狀態為'N'的未處理數據,因此通過索引來訪問是最優的。反之,謂語為'Y'的查詢就不應該使用索引,因為使用這個謂語幾乎所有行都將被取出。
4、考慮列的排序,並安排好索引中列值的順序以使其與應用訪問模式相適應。例如,在SH模式下的Sales表中,Prod_id列的選擇度為1/2,而Cust_id列的選擇度為1/7059。看上去似乎Cust_id列是進行索引更好的候選因為該列的選擇度比較低。但是,如果應用聲明了Prod_id列上的等式謂語而沒有在謂語中聲明Cust_id列,那么Cust_id列就不必進行索引,即使Cust_id列具有更好的選擇度。如果應用在Prod_id列和Cust_id列都使用了謂語,那么最好是在這兩列都建立索引並將Cust_id列作為引導列。而要考慮的是列是否在謂語中使用,而不是完全依賴於列的選擇度。
5、還需要考慮索引的成本。插入、刪除以及更新(更新索引列)都需要維護索引。如果索引列需要進行大量更新的話,這個索引的維護成本就更高,因為建索引的列的更新會導致索引內部發生刪除和插入。這也有可能會引入額外的資源爭奪點。
6、考慮列的長度。建有索引的列越長,索引也就越大。索引的成本就可能會超過有索引帶來的全部好處。較大的索引尺寸也會增加撤銷和重做區的大小。
7、在多列索引中,如果引導列只有很少的唯一值,考慮將該索引建立為壓縮索引。這些索引的尺寸將會變得更小,因為壓縮索引中不保存重復值。
8、如果謂語在索引列上使用函數,這一列上的索引就不會被選用。例如,謂語to_char(prod_id)=:B1就在Prod_id列上應用了一個to_char函數。不太可能為這個謂語選用Prod_id列上的常規索引,需要在to_char(prod_id)列上來建立一個基於函數的索引。
9、不要在需要大幅修改的列上建立位圖索引。位圖索引的內部實現更適合於只有很少唯一值的只讀列。如果索引進行了更新,位圖索引的大小可能會迅速增大。對一個位圖索引的過多修改還可能會導致大量的鎖資源爭奪。位圖索引在數據倉庫應用中的使用更普遍。

 

空值問題:
在SQL語句中經常會聲明IS NULL謂語。空值不存儲在某個單獨列的索引中,因此謂語IS NULL將不會使用單列索引。空值索引是存儲在多列索引中的,一般通過使用另一個虛擬列來創建多列索引,就可以在IS NULL子句中啟用索引。
select * from t1 where n1 is null;  //未啟用
create index t1_n10 on t1(n1,0);  //使用虛擬列創建多列索引
select * from t1 where n1 is null;  //啟用索引


備注:

[1][2]基數、選擇度:基 數被定義為一個謂語或執行步驟預期獲取的數據行數。考慮一個假設列值均勻分布的列上的簡單等式謂語。通過表中的數據行數與表中唯一值的個數相除來算出基 數。例如,在Sales表中,有918K行數據而Prod_id列上72個唯一值,因此Prod_id列上的等式謂語基數就是918K/72=12 750。那么,換句話說,謂語Prod_id=:b1預計將取出12750行數據。具有較低基數的列更適合作為索引的候選,因為索引的選擇度要更好。對於 每個值都是唯一的列,等式謂語的基數為1。選擇度是一個從0到1的度量值,簡單定義為1/NDV,其中NDV表示唯一值的數目。因此,一個位於的數據可以 定義為選擇度乘以表中的數據行數。

 

參考資料:

1、《Oracle SQL高級編程》 人民郵電出版社


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM