MySQL用B+樹(而不是B樹)作索引的緣由

 

https://www.jianshu.com/p/7ce804f97967算法

衆所周知,MySQL的索引使用了B+樹的數據結構。那麼爲何不用B樹呢?
先看一下B樹和B+樹的區別。數據庫

1.B樹

維基百科對B樹的定義爲「在計算機科學中,B樹(B-tree)是一種樹狀數據結構,它可以存儲數據、對其進行排序並容許以O(log n)的時間複雜度運行進行查找、順序讀取、插入和刪除的數據結構。B樹,歸納來講是一個節點能夠擁有多於2個子節點的二叉查找樹。與自平衡二叉查找樹不一樣,B-樹爲系統最優化大塊數據的讀和寫操做。B-tree算法減小定位記錄時所經歷的中間過程,從而加快存取速度。廣泛運用在數據庫和文件系統。」緩存

B 樹能夠看做是對2-3查找樹的一種擴展,即他容許每一個節點有M-1個子節點。數據結構

1.1定義

  • 根節點至少有兩個子節點
  • 每一個節點有M-1個key,而且以升序排列
  • 位於M-1和M key的子節點的值位於M-1 和M key對應的Value之間
  • 其它節點至少有M/2個子節點
    下圖是一個M=4 階的B樹:性能


     
    M=4的B樹

    能夠看到B樹是2-3樹的一種擴展,他容許一個節點有多於2個的元素。優化

B樹的插入及平衡化操做和2-3樹很類似,這裏就不介紹了。下面是往B樹中依次插入
6 10 4 14 5 11 15 3 2 12 1 7 8 8 6 3 6 21 5 15 15 6 32 23 45 65 7 8 6 5 4 的演示動畫:動畫


 
btreebuild

2.B+樹

B+樹是對B樹的一種變形樹,它與B樹的差別在於:ui

  • 有k個子結點的結點必然有k個關鍵碼。
  • 非葉結點僅具備索引做用,跟記錄有關的信息均存放在葉結點中。
  • 樹的全部葉結點構成一個有序鏈表,能夠按照關鍵碼排序的次序遍歷所有記錄。
    以下圖是一個B+樹:3d


     
    M=4的B+樹

    下圖是B+樹的創建過程:指針


     
    Bplustreebuild.gif

B+樹和B樹的區別

B+樹的非葉子結點只包含導航信息,不包含實際的值,全部的葉子結點和相連的節點使用鏈表相連,便於區間查找和遍歷。
B+ 樹的優勢在於:

  • IO次數更少:因爲B+樹在內部節點上不包含數據信息,所以在內存頁中可以存放更多的key。 數據存放的更加緊密,具備更好的空間局部性。所以訪問葉子節點上關聯的數據也具備更好的緩存命中率。
  • 遍歷更加方便:B+樹的葉子結點都是相鏈的,所以對整棵樹的遍歷只須要一次線性遍歷葉子結點便可。並且因爲數據順序排列而且相連,因此便於區間查找和搜索。而B樹則須要進行每一層的遞歸遍歷。相鄰的元素可能在內存中不相鄰,因此緩存命中性沒有B+樹好。

可是B樹也有優勢,其優勢在於,因爲B樹的每個節點都包含key和value,所以常常訪問的元素可能離根節點更近,所以訪問也更迅速。下面是B 樹和B+樹的區別圖:


 
B樹和B+樹的區別圖

爲何MySQL選擇B+樹作索引

一、 B+樹的磁盤讀寫代價更低:B+樹的內部節點並無指向關鍵字具體信息的指針,所以其內部節點相對B樹更小,若是把全部同一內部節點的關鍵字存放在同一盤塊中,那麼盤塊所能容納的關鍵字數量也越多,一次性讀入內存的須要查找的關鍵字也就越多,相對IO讀寫次數就下降了。

二、B+樹的查詢效率更加穩定:因爲非終結點並非最終指向文件內容的結點,而只是葉子結點中關鍵字的索引。因此任何關鍵字的查找必須走一條從根結點到葉子結點的路。全部關鍵字查詢的路徑長度相同,致使每個數據的查詢效率至關。

三、B+樹更便於遍歷:因爲B+樹的數據都存儲在葉子結點中,分支結點均爲索引,方便掃庫,只須要掃一遍葉子結點便可,可是B樹由於其分支結點一樣存儲着數據,咱們要找到具體的數據,須要進行一次中序遍歷按序來掃,因此B+樹更加適合在區間查詢的狀況,因此一般B+樹用於數據庫索引。

四、B+樹更適合基於範圍的查詢:B樹在提升了IO性能的同時並無解決元素遍歷的我效率低下的問題,正是爲了解決這個問題,B+樹應用而生。B+樹只須要去遍歷葉子節點就能夠實現整棵樹的遍歷。並且在數據庫中基於範圍的查詢是很是頻繁的,而B樹不支持這樣的操做或者說效率過低。

參考

做者:Jarkata 連接:https://www.jianshu.com/p/7ce804f97967 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索