Oracle中的位圖索引和函數索引


位圖索引

同樣的,先說是什么,再說為什么。

上篇我們說過BTREE索引是將數據表的索引列和行號排序后以樹狀形式存在磁盤中。那位圖索引是什么樣的呢?

現有如下日志表,有操作類型字段op_type,該字段的取值只有“查看”、“查詢”、“新增”、“修改”和“刪除”。

如下表,當在op_type列建位圖索引,如果某數據行取值是“查看”則將該行的“查看”的單元格記為1,在其他取值上記0;如果取值是“修改”則在該行的“修改”的單元格記1,其他取值上記0:

 

 

同理,在操作用戶列建位圖索引如下:

 

查看如下計數語句在各種情況下的效率如何呢?

select count(*) from tsys_log_click;

未建索引:

建了BTREE索引:

在操作類型op_type列上建位圖索引之后:

我們在不同前提下進行了三次統計查詢,在未建索引的情況下,統計查詢走的全表掃描,代價是223,邏輯讀是838;在非空列r_id上建BTREE索引之后,統計查詢走的索引快速掃描,代價是46,邏輯讀是193;在操作類型列上建位圖索引之后,統計查詢走的位圖索引快速掃描,代價是3,邏輯讀是7。

所以,在統計查詢中,代價最高的是全表掃描;在非空列上建BTREE索引后,一般走BTREE索引的效率要比全表掃描高;最快的是在列取值高度重復的列上建位圖索引。

 

BTREE索引存儲的是列值,而位圖索引存儲的是比特位值,加入位圖索引所在的列只有一個取值,比如操作類別列只有“查看”,這時整個位圖索引的大小大致等於行數乘以這1個字節,如果操作類型有“查看”和“查詢”,最多也就是只有“查看”的情況下的兩倍大,所以位圖索引在重復度很低時,體積非常小,所以count(*)統計非常快。

當我們在做

where op_type = '刪除' and call_user = 'xrisk'

這樣的即席查詢時,如果在條件列上建了位圖索引,那么查詢其實就是個邏輯運算,在我們上面兩張表中,找出這兩列的取值都為1(與運算)的結果就是了。

 

但是建了位圖索引的數據表,在更新數據時會有很大的問題:

當位圖索引列的取值越少,更新數據時,維護索引影響的列數就越多,比如操作類別列如果取值只有“查看”和“查詢”的話,鍵值為“查看”的索引條目指向了數據庫一半以上的數據,更新就要影響了一半以上的數據。

 

所以,如果某列是被頻繁更新的,或者頻繁插入記錄的表,建位圖索引是不合適的。上面還有一條,這個列的取值是高度重復的,否則我們像上面構建的位圖索引的所謂的表也會很龐大。

 

函數索引

如果對索引列做運算會導致索引無法使用:

select * from tsys_log_click where upper(call_user) = 'TOM';

即使在call_user列上建了索引,這樣的查詢也不會走索引。但我們可以連帶着函數一起建索引,即函數索引:

函數索引的性能是在全表掃描和普通索引之間

所以應該盡可能避免函數索引。例如

select * from tsys_user where substr(user_name,1,3) = 'Tom';

可以改寫成 select * from tsys_user where user_name like 'Tom%';

 

 


免責聲明!

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



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