Hash索引的查找速度很快,幾乎是O1的,但是為什么不適用 HashMap 來做數據庫索引呢?
1、區間值難找。因為單個值計算會很快,而找區間值,比如 100 < id < 200 就悲催了,需要遍歷全部hash節點。
2、排序難。通過hash算法,也就是壓縮算法,可能會很大的值和很小的值落在同一個hash桶里,比如一萬個數壓縮成1000個數存到hash桶里,也就是會產生hash沖突。
MySQL的InnoDB存儲引擎支持以下常見索引:B+tree索引(最關鍵)、全文索引、Hash索引(內部)
二叉樹、二叉查找樹
B+tree是通過二叉查找樹,再由平衡二叉樹,B樹演化而來。一個int有序數組轉化為二叉查找樹示例圖,取最中間值作為第一節點:
在二叉查找樹設計不良的情況下,可能會產生極端情況,就是只存在右指數的情況,這時查找效率反而會降低。這時為了提高性能,就產生了平衡二叉樹(AVL樹)概念,也就是兩個指數的之間的高度差不能大於1.
所有的節點都有,稱之為滿二叉樹。
二叉查找樹通過左旋右旋,能夠很好的實現平衡二叉樹,但是為什么不使用二叉樹來作為mysql的索引呢?因為二叉樹在數據量大的情況下會太高!而磁盤的每次IO時間需要0.01秒!
B+tree索引
B-tree和B+tree和B*tree的區別?
1)B-tree的中間節點里存放:關鍵字、數據區、子節點引用。
而B+tree的中間節點沒有數據區,B+tree會在底層的葉子節點中才會放數據。
2)B+tree的葉子節點存放數據,而葉子節點也會多一個指針,指向下一個葉子節點。
3)B+tree只是葉子節點有個指針指向下一個葉子節點,而B*tree連中間索引節點都有個指針指向下一個中間索引節點。(oracle里用的是B*tree)
B-tree和B+tree都是一種平衡樹,不會產生極度傾斜的情況,而且數據的存儲都是有序的。
新增數據時,葉子節點滿的情況下,會分裂出葉子節點,把原葉子節點的中間數據提到上一層。
刪除數據時,葉子節點會萎縮,可能會層層萎縮。
B-tree和B+tree又被稱為多路查找樹,或者多叉平衡查找樹。
重點:B+tree每個節點的葉子節點是多個,而二叉樹每個節點的葉子節點都是2個,所以B+tree的節點高度遠低於二叉樹。
MySQL官方innodb存儲引擎doc文檔: https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html
索引使用案例
聯合索引設計時,比如:CREATE INDEX idx_name_age_address ON t1 (name, age, address) 則在B+tree里存放的每個索引節點有3行,第一行按照name順序排列,第二行按照name值相同的情況下age順序排列,第三行按照name值相同age值也相同的情況下address順序排列。所以聯合索引使用最左原則就是這個原理。
根據上述原理,select age from t1 where name = 'zhangsan' 這個SQL要查詢的age值剛好是name聯合索引里的第二行索引,就不需要再回表到主鍵索引去查,直接從聯合索引里取值即可,這被稱為索引覆蓋。
回表: 回表是典型的隨機IO,能盡量不回表就不回表,盡量使用主鍵索引或者二級覆蓋索引這類查詢。
MySQL索引使用例子,參考《mysql5.7版本的explain解析》
end.