前言
數據庫是整個計算機領域里,任何項目必須依賴的基礎服務,數據庫相關的面試題也是面試官綜合考察面試者基礎知識及項目經驗的必問題目。
上一章共24篇,我們講解的算法題章節,知道了常被面試官問到的算法面試題。
本篇屬於數據庫系列,今天我們分析的是為什么Mysql用B+樹做索引而不用B-樹或平衡二叉樹。
概要
要分析這個問題,我們首先來分別看一下B+樹,B樹,平衡二叉樹的結構特征。
平衡二叉樹
1.非葉子節點最多擁有兩個子節點。
2.非葉子節值大於左邊子節點、小於右邊子節點。
3.樹的左右兩邊的層級數相差不會大於1。
4.沒有值相等重復的節點。

B-樹
B-樹和平衡二叉樹稍有不同的是B-樹屬於多叉樹又名平衡多路查找樹(查找路徑不只兩個)。
- 1.在一個節點中,存放着數據(包括key和data)以及指針,且相互間隔。
- 2.同一個節點,key增序。
- 3.一個節點最左邊的指針不為空,則它指定的節點左右的key小於最左邊的key。右邊同理。中間的指針指向的節點的key位於相鄰兩個key的中間。
- 4.B-Tree中不同節點存放的key和指針可能數量不一致,但是每個節點的域和上限是一致的,所以在實現中B-Tree往往對每個節點申請同等大小的空間。
- 5.每個非葉子節點由n-1個key和n個指針組成,其中d<=n<=2d。

B+樹

- 1.內節點不存儲data,只存儲key和指針;葉子節點不存儲指針,存key和data。
- 2.內節點和葉子節點大小不同。
- 3.每個節點的指針上限為2d而不是2d+1。
平衡二叉樹的問題
為了解決二叉樹數據有序時出現的線性插入樹太深問題,樹的深度會明顯降低,雖然極大提高性能,但是當數據量很大時,一般mysql中一張表達到3-5百萬條數據
是很普遍,因此平衡二叉樹的深度會非常大,mysql讀取時會消耗大量IO。
不僅如此,計算機從磁盤讀取數據時以頁(4KB)為單位的,每次讀取4096byte。平衡二叉樹每個節點只保存了一個關鍵字(如int即4byte),浪費了4092byte,極大的浪費了讀取空間。
B-樹相對於平衡二叉樹的優點
平衡二叉樹基本都是存儲在內存中才會使用的數據結構。
在大規模數據存儲的時候,平衡二叉樹往往出現由於樹的深度過大而造成磁盤IO讀寫過於頻繁,進而導致效率低下的情況。
我們知道要獲取磁盤上數據,必須先通過磁盤移動臂移動到數據所在的柱面,然后找到指定盤面,接着旋轉盤面找到數據所在的磁道,最后對數據進行讀寫。
磁盤IO代價主要花費在查找所需的柱面上,樹的深度過大會造成磁盤IO頻繁讀寫。根據磁盤查找存取的次數往往由樹的高度所決定。
所以,只要我們通過某種較好的樹結構減少樹的結構盡量減少樹的高度,B-樹可以有多個子女,從幾十到上千,可以降低樹的高度,解決了平衡二叉樹讀取消耗大量內存空間的問題。
B-樹的其他優點
數據庫系統的設計者巧妙利用了磁盤預讀原理,將一個節點的大小設為等於一個頁,這樣每個節點只需要一次I/O就可以完全載入。
為了達到這個目的,在實際實現B-Tree還使用了如下技巧:
每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也存儲在一個頁里,加之計算機存儲分配都是按頁對齊的,就實現了一個node只需一次I/O。
另外如果經常訪問的數據離根節點很近,而B樹的非葉子節點本身存有關鍵字其數據的地址,所以這種數據檢索的時候會相對其他數據結構更快。
B+樹相對B-樹的優點
B+樹只有葉節點存放數據,其余節點用來索引,而B-樹是每個索引節點都會有Data域。
所以從Mysql(Inoodb)的角度來看,B+樹是用來充當索引的,一般來說索引非常大,尤其是關系性數據庫這種數據量大的索引能達到億級別。
所以為了減少內存的占用,索引也會被存儲在磁盤上。那么Mysql如何衡量查詢效率呢?– 磁盤IO次數。
B-樹/B+樹 的特點就是每層節點數目非常多,層數很少,目的就是為了就少磁盤IO次數。
但是B-樹的每個節點都有data域(指針),這無疑增大了節點大小,增加了磁盤IO次數,磁盤IO一次讀出的數據量大小是固定的,單個數據變大,每次讀出的就少,IO次數增多,一次IO多耗時。
所以我們可以看到B+樹的優點:
1、B+樹的層級更少。
相較於B樹B+每個非葉子節點存儲的關鍵字數更多,樹的層級更少所以查詢數據更快;
2、B+樹查詢速度更穩定。
B+所有關鍵字數據地址都存在葉子節點上,所以每次查找的次數都相同所以查詢速度要比B樹更穩定;
3、B+樹天然具備排序功能。
B+樹所有的葉子節點數據構成了一個有序鏈表,在查詢大小區間的數據時候更方便,數據緊密性很高,緩存的命中率也會比B樹高。
4、B+樹全節點遍歷更快。
B+樹遍歷整棵樹只需要遍歷所有的葉子節點即可,而不需要像B樹一樣需要對每一層進行遍歷,這有利於數據庫做全表掃描。
總結
今天我們分析了平衡二叉樹、B-樹、B+樹的數據結構特征及各自優點,知道了Mysql用B+樹做索引而不用B-樹或平衡二叉樹的原因,本專欄的后續文章中,筆者會不斷的去深入總結名企常見面試題的常用思路和解決方案,相信能很大程度幫助大家早日拿到更高水平的Offer。