在MySQL裏經常使用的索引數據結構有B+樹索引和哈希索引兩種,咱們來看下這兩種索引數據結構的區別及其不一樣的應用建議。mysql
備註:先說下, 在MySQL文檔裏,其實是把B+樹索引寫成了BTREE ,例如像下面這樣的寫法:算法
CREATE TABLE t(sql
aid int unsigned not null auto_increment,數據庫
userid int unsigned not null default 0,數據結構
username varchar(20) not null default ‘’,ui
detail varchar(255) not null default ‘’,spa
primary key(aid),指針
unique key(uid) USING BTREE ,排序
key (username(12)) USING BTREE — 此處 uname 列只建立了最左12個字符長度的部分索引索引
)engine=InnoDB;
一個經典的 B+樹索引數據結構 見下圖:
B+樹是一個平衡的多叉樹,從根節點到每一個葉子節點的高度差值不超過1,並且同層級的節點間有指針相互連接。
在B+樹上的常規檢索,從根節點到葉子節點的搜索效率基本至關,不會出現大幅波動,並且基於索引的順序掃描時,也能夠利用雙向指針快速左右移動,效率很是高。
所以,B+樹索引被普遍應用於數據庫、文件系統等場景。順便說一下,xfs文件系統比ext3/ext4效率高不少的緣由之一就是,它的文件及目錄索引結構所有采用B+樹索引,而ext3/ext4的文件目錄結構則採用Linked list, hashed B-tree、Extents/Bitmap等索引數據結構,所以在高I/O壓力下,其IOPS能力不如xfs。
詳細可參見:
https://en.wikipedia.org/wiki/Ext4https://en.wikipedia.org/wiki/XFS
而 哈希索引的示意圖 則是這樣的:
簡單地說, 哈希索引就是採用必定的哈希算法 ,把鍵值換算成新的哈希值,檢索時不須要相似B+樹那樣從根節點到葉子節點逐級查找,只需一次哈希算法便可馬上定位到相應的位置,速度很是快。
從上面的圖來看,B+樹索引和哈希索引的明顯區別是:
若是是等值查詢,那麼哈希索引明顯有絕對優點,由於只須要通過一次算法便可找到相應的鍵值;固然了,這個前提是,鍵值都是惟一的。若是鍵值不是惟一的,就須要先找到該鍵所在位置,而後再根據鏈表日後掃描,直到找到相應的數據;
從示意圖中也能看到, 若是是範圍查詢檢索,這時候哈希索引就毫無用武之地了 ,由於原先是有序的鍵值,通過哈希算法後,有可能變成不連續的了,就沒辦法再利用索引完成範圍查詢檢索;
同理, 哈希索引也沒辦法利用索引完成排序 ,以及like ‘xxx%’ 這樣的部分模糊查詢(這種部分模糊查詢,其實本質上也是範圍查詢);
哈希索引也不支持多列聯合索引的最左匹配規則;
B+樹索引的關鍵字檢索效率比較平均,不像B樹那樣波動幅度大, 在有大量重複鍵值狀況下,哈希索引的效率也是極低的,由於存在所謂的哈希碰撞問題 。
在MySQL中,只有HEAP/MEMORY引擎表才能顯式支持哈希索引(NDB也支持,但這個不經常使用),InnoDB引擎的自適應哈希索引(adaptive hash index)不在此列,由於這不是建立索引時可指定的。
還須要注意到:HEAP/MEMORY引擎表在mysql實例重啓後,數據會丟失。
一般,B+樹索引結構適用於絕大多數場景,像下面這種場景用哈希索引才更有優點:
在HEAP表中,若是存儲的數據重複度很低(也就是說基數很大),對該列數據以等值查詢爲主,沒有範圍查詢、沒有排序的時候,特別適合採用哈希索引
例如這種SQL:SELECT … FROM t WHERE C1 = ?; — 僅等值查詢
在大多數場景下,都會有範圍查詢、排序、分組等查詢特徵,用B+樹索引就能夠了。