為什么數據庫中要使用B+tree索引,而不用hash索引?MySQL中的B+tree索引介紹


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.


免責聲明!

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



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