位图索引,数据库索引浅浅的学习
? ? ? ? ? ? 摘自http://www.cnblogs.com/LBSer/p/3322630.html
?
位圖(BitMap)索引
前段時間聽同事分享,偶爾講起Oracle數據庫的位圖索引,頓時大感興趣。說來慚愧,在這之前對位圖索引一無所知,因此趁此機會寫篇博文介紹下位圖索引。
1. 案例
有張表名為table的表,由三列組成,分別是姓名、性別和婚姻狀況,其中性別只有男和女兩項,婚姻狀況由已婚、未婚、離婚這三項,該表共有100w個記錄?,F在有這樣的查詢:? ? ?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的簡稱。這個數據結構一般用于數據庫的索引,綜合效率較高?!俣劝倏?/p>
不適合:
- 單列索引的列不能包含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頻繁的列,代價很高。
轉載于:https://www.cnblogs.com/yedu/p/9198724.html
總結
以上是生活随笔為你收集整理的位图索引,数据库索引浅浅的学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript表单基本验证
- 下一篇: 【转】oracle数据库中varchar