Mysql InnoDB B+樹索引和雜湊索引的區別? MongoDB 為什麼使用B-樹?

搜雲庫技術團隊發表於2018-04-04

B-樹和B+樹最重要的一個區別就是B+樹只有葉節點存放資料,其餘節點用來索引,而B-樹是每個索引節點都會有Data域。

B+樹

B+樹是為磁碟及其他儲存輔助裝置而設計一種平衡查詢樹(不是二叉樹)。B+樹中,所有記錄的節點按大小順序存放在同一層的葉節點中,各葉節點用指標進行連線。

資料庫中B+樹索引分為聚集索引(clustered index)和非聚集索引(secondary index).這兩種索引的共同點是內部都是B+樹,高度都是平衡的,葉節點存放著所有資料。不同點是葉節點是否存放著一整行資料。

B+樹有如下特點:

  • B+樹每個節點可以包含更多的節點,這樣做有兩個原因,一個是降低樹的高度。另外一個是將資料範圍變為多個區間,區間越多,資料檢索越快。
  • 每個節點不再只是儲存一個key了,可以儲存多個key。
  • 非葉子節點儲存key,葉子節點儲存key和資料。
  • 葉子節點兩兩指標相互連結,順序查詢效能更高。

通俗的講

  • B+樹的非葉子節點只是儲存key,佔用空間非常小,因此每一層的節點能索引到的資料範圍更加的廣。換句話說,每次IO操作可以搜尋更多的資料。
  • 葉子節點兩兩相連,符合磁碟的預讀特性。比如葉子節點儲存50和55,它有個指標指向了60和62這個葉子節點,那麼當我們從磁碟讀取50和55對應的資料的時候,由於磁碟的預讀特性,會順便把60和62對應的資料讀取出來。這個時候屬於順序讀取,而不是磁碟尋道了,加快了速度。
  • 支援範圍查詢,而且部分範圍查詢非常高效,每個節點能索引的範圍更大更精確,也意味著 B+樹單次磁碟IO的資訊量大於B-樹,I/O效率更高。

原因是資料都是儲存在葉子節點這一層,並且有指標指向其他葉子節點,這樣範圍查詢只需要遍歷葉子節點這一層,無需整棵樹遍歷。

區域性性原理與磁碟預讀

由於磁碟的存取速度與記憶體之間鴻溝,為了提高效率,要儘量減少磁碟I/O.磁碟往往不是嚴格按需讀取,而是每次都會預讀,磁碟讀取完需要的資料,會順序向後讀一定長度的資料放入記憶體。而這樣做的理論依據是電腦科學中著名的區域性性原理:

當一個資料被用到時,其附近的資料也通常會馬上被使用,程式執行期間所需要的資料通常比較集中

B-樹

B-樹,這裡的 B 表示 balance( 平衡的意思),B-樹是一種多路自平衡的搜尋樹 它類似普通的平衡二叉樹,不同的一點是B-樹允許每個節點有更多的子節點。

B-樹有如下特點

  • 所有鍵值分佈在整顆樹中。
  • 任何一個關鍵字出現且只出現在一個結點中。
  • 搜尋有可能在非葉子結點結束。
  • 在關鍵字全集內做一次查詢,效能逼近二分查詢。

B-樹和B+樹的區別

  • B+樹內節點不儲存資料,所有資料儲存在葉節點導致查詢時間複雜度固定為 log n。
  • B-樹查詢時間複雜度不固定,與 key 在樹中的位置有關,最好為O(1)。
  • B+樹葉節點兩兩相連可大大增加區間訪問性,可使用在範圍查詢等。
  • B-樹每個節點 key 和 data 在一起,則無法區間查詢。
  • B+樹更適合外部儲存(儲存磁碟資料)。由於內節點無 data 域,每個節點能索引的範圍更大更精確。

MongoDB 為什麼使用B-樹?

B+樹內節點不儲存資料,所有 data 儲存在葉節點導致查詢時間複雜度固定為 log n。而B-樹查詢時間複雜度不固定,與 key 在樹中的位置有關,最好為O(1)

我們說過,儘可能少的磁碟 IO 是提高效能的有效手段。MongoDB 是聚合型資料庫,而 B-樹恰好 key 和 data 域聚合在一起

至於MongoDB為什麼使用B-樹而不是B+樹,可以從它的設計角度來考慮,它並不是傳統的關係性資料庫,而是以Json格式作為儲存的nosql,目的就是高效能,高可用,易擴充套件。首先它擺脫了關係模型,上面所述的優點2需求就沒那麼強烈了,其次Mysql由於使用B+樹,資料都在葉節點上,每次查詢都需要訪問到葉節點,而MongoDB使用B-樹,所有節點都有Data域,只要找到指定索引就可以進行訪問,無疑單次查詢平均快於Mysql

雜湊索引

簡單地說,雜湊索引就是採用一定的雜湊演算法,把鍵值換算成新的雜湊值,檢索時不需要類似B+樹那樣從根節點到葉子節點逐級查詢,只需一次雜湊演算法即可立刻定位到相應的位置,速度非常快。

B+樹索引和雜湊索引的區別

  • 如果是等值查詢,那麼雜湊索引明顯有絕對優勢,因為只需要經過一次演算法即可找到相應的鍵值;當然了,這個前提是,鍵值都是唯一的。如果鍵值不是唯一的,就需要先找到該鍵所在位置,然後再根據連結串列往後掃描,直到找到相應的資料。
  • 如果是範圍查詢檢索,這時候雜湊索引就毫無用武之地了,因為原先是有序的鍵值,經過雜湊演算法後,有可能變成不連續的了,就沒辦法再利用索引完成範圍查詢檢索。
  • 同理,雜湊索引也沒辦法利用索引完成排序,以及like ‘xxx%’ 這樣的部分模糊查詢(這種部分模糊查詢,其實本質上也是範圍查詢)。
  • 雜湊索引也不支援多列聯合索引的最左匹配規則
  • B+樹索引的關鍵字檢索效率比較平均,不像B樹那樣波動幅度大,在有大量重複鍵值情況下,雜湊索引的效率也是極低的,因為存在所謂的雜湊碰撞問題
  • 解決Hash碰撞衝突方法總結 blog.csdn.net/zeb_perfect…

備註:以上內容均摘抄自網路,並非原創,僅供個人學習交流使用,望各路大牛,發現不對的地方,不吝賜教,留言即可

參考

  • https://blog.csdn.net/wwh578867817/article/details/50493940
  • https://segmentfault.com/a/1190000004690721
  • http://www.cnblogs.com/heiming/p/5865101.html

推薦閱讀

關注微信公眾號福利

關注微信公眾號「搜雲庫」獲取最新文章

福利】公眾號後臺回覆 “進群
福利】邀請您進微信 “技術分享群
福利】群裡有很多技術大佬,免費提問,互相學習

關注公眾號-搜雲庫
搜雲庫

相關文章