摘自http://www.cnblogs.com/LBSer/p/3322630.html
位圖(BitMap)索引
前段時間聽同事分享,偶爾講起Oracle數據庫的位圖索引,頓時大感興趣。說來慚愧,在這之前對位圖索引一無所知,因此趁此機會寫篇博文介紹下位圖索引。
1. 案例
有張表名為table的表,由三列組成,分別是姓名、性別和婚姻狀況,其中性別只有男和女兩項,婚姻狀況由已婚、未婚、離婚這三項,該表共有100w個記錄。現在有這樣的查詢: select * from table where Gender=‘男’ and Marital=“未婚”;
| 姓名(Name) |
性別(Gender) |
婚姻狀況(Marital) |
| 張三 |
男 |
已婚 |
| 李四 |
女 |
已婚 |
| 王五 |
男 |
未婚 |
| 趙六 |
女 |
離婚 |
| 孫七 |
女 |
未婚 |
| ... |
... |
... |
1)不使用索引
不使用索引時,數據庫只能一行行掃描所有記錄,然后判斷該記錄是否滿足查詢條件。
2)B樹索引
對於性別,可取值的范圍只有'男','女',並且男和女可能各站該表的50%的數據,這時添加B樹索引還是需要取出一半的數據, 因此完全沒有必要。相反,如果某個字段的取值范圍很廣,幾乎沒有重復,比如身份證號,此時使用B樹索引較為合適。事實上,當取出的行數據占用表中大部分的數據時,即使添加了B樹索引,數據庫如oracle、mysql也不會使用B樹索引,很有可能還是一行行全部掃描。
2. 位圖索引出馬
如果用戶查詢的列的基數非常的小, 即只有的幾個固定值,如性別、婚姻狀況、行政區等等。要為這些基數值比較小的列建索引,就需要建立位圖索引。
對於性別這個列,位圖索引形成兩個向量,男向量為10100...,向量的每一位表示該行是否是男,如果是則位1,否為0,同理,女向量位01011。
| RowId |
1 |
2 |
3 |
4 |
5 |
... |
| 男 |
1 |
0 |
1 |
0 |
0 |
|
| 女 |
0 |
1 |
0 |
1 |
1 |
|
對於婚姻狀況這一列,位圖索引生成三個向量,已婚為11000...,未婚為00100...,離婚為00010...。
| RowId |
1 |
2 |
3 |
4 |
5 |
... |
| 已婚 |
1 |
1 |
0 |
0 |
0 |
|
| 未婚 |
0 |
0 |
1 |
0 |
1 |
|
| 離婚 |
0 |
0 |
0 |
1 |
0 |
|
當我們使用查詢語句“select * from table where Gender=‘男’ and Marital=“未婚”;”的時候 首先取出男向量10100...,然后取出未婚向量00100...,將兩個向量做and操作,這時生成新向量00100...,可以發現第三位為1,表示該表的第三行數據就是我們需要查詢的結果。
| RowId |
1 |
2 |
3 |
4 |
5 |
| 男 |
1 |
0 |
1 |
0 |
0 |
| and |
|
|
|
|
|
| 未婚 |
0 |
0 |
1 |
0 |
1 |
| 結果 |
0 |
0 |
1 |
0 |
0 |
3.位圖索引的適用條件
上面講了,位圖索引適合只有幾個固定值的列,如性別、婚姻狀況、行政區等等,而身份證號這種類型不適合用位圖索引。
此外,位圖索引適合靜態數據,而不適合索引頻繁更新的列。舉個例子,有這樣一個字段busy,記錄各個機器的繁忙與否,當機器忙碌時,busy為1,當機器不忙碌時,busy為0。
這個時候有人會說使用位圖索引,因為busy只有兩個值。好,我們使用位圖索引索引busy字段!假設用戶A使用update更新某個機器的busy值,比如update table set table.busy=1 where rowid=100;,但還沒有commit,而用戶B也使用update更新另一個機器的busy值,update table set table.busy=1 where rowid=12; 這個時候用戶B怎么也更新不了,需要等待用戶A commit。
原因:用戶A更新了某個機器的busy值為1,會導致所有busy為1的機器的位圖向量發生改變,因此數據庫會將busy=1的所有行鎖定,只有commit之后才解鎖。
以下內容轉載自:https://blog.csdn.net/pzqingchong/article/details/50971854
當前測試的版本是Mysql 5.5.25只有BTree和Hash兩種索引類型,默認為BTree。Oracle或其他類型數據庫中會有Bitmap索引(位圖索引),這里作為比較也一起提供。
BTree索引
BTree(多路搜索樹,並不是二叉的)是一種常見的數據結構。使用BTree結構可以顯著減少定位記錄時所經歷的中間過程,從而加快存取速度。按照翻譯,B 通常認為是Balance的簡稱。這個數據結構一般用於數據庫的索引,綜合效率較高。——百度百科
不適合:
- 單列索引的列不能包含null的記錄,復合索引的各個列不能包含同時為null的記錄,否則會全表掃描;
- 不適合鍵值較少的列(重復數據較多的列);
- 前導模糊查詢不能利用索引(like '%XX'或者like '%XX%')
Hash散列索引
Hash散列索引是根據HASH算法來構建的索引。雖然 Hash 索引效率高,但是 Hash 索引本身由於其特殊性也帶來了很多限制和弊端,主要有以下這些。
適合:
- 精確查找非常快(包括= <> 和in),其檢索效率非常高,索引的檢索可以一次定位,不像BTree 索引需要從根節點到枝節點,所以 Hash 索引的查詢效率要遠高於 B-Tree 索引。
不適合:
- 不適合模糊查詢和范圍查詢(包括like,>,<,between……and等),由於 Hash 索引比較的是進行 Hash 運算之后的 Hash 值,所以它只能用於等值的過濾,不能用於基於范圍的過濾,因為經過相應的 Hash 算法處理之后的 Hash 值的大小關系,並不能保證和Hash運算前完全一樣;
- 不適合排序,數據庫無法利用索引的數據來提升排序性能,同樣是因為Hash值的大小不確定;
- 復合索引不能利用部分索引字段查詢,Hash 索引在計算 Hash 值的時候是組合索引鍵合並后再一起計算 Hash 值,而不是單獨計算 Hash 值,所以通過組合索引的前面一個或幾個索引鍵進行查詢的時候,Hash 索引也無法被利用。
- 同樣不適合鍵值較少的列(重復值較多的列);
Bitmap位圖索引
就是用位圖表示的索引,對列的每個鍵值建立一個位圖。相對於BTree索引,占用的空間非常小,創建和使用非常快。位圖索引由於只存儲鍵值的起止Rowid和位圖,占用的空間非常少。如test表中有state這樣一列,10行數據如下:
10 20 30 20 10 30 10 30 20 30
那么會建立三個位圖,如下:
BLOCK1 KEY=10 1 0 0 0 1 0 1 0 0 0
BLOCK2 KEY=20 1 0 0 0 1 0 1 0 0 0
BLOCK3 KEY=30 1 0 0 0 1 0 1 0 0 0
適合
- 適合決策支持系統;
- 當select count(XX) 時,可以直接訪問索引中一個位圖就快速得出統計數據;
- 當根據鍵值做and,or或 in(x,y,..)查詢時,直接用索引的位圖進行或運算,快速得出結果行數據。
不適合
- 不適合鍵值較多的列(重復值較少的列);
- 不適合update、insert、delete頻繁的列,代價很高。
