搞懂這個問題以前,咱們首先來看一下MySQL表的存儲結構,再分別對比二叉樹、多叉樹、B樹和B+樹的區別就都懂了。mysql
MySQL的存儲結構
表存儲結構
單位:表>段>區>頁>行sql
在數據庫中, 不論讀一行,仍是讀多行,都是將這些行所在的頁進行加載。也就是說存儲空間的基本單位是頁。
一個頁就是一棵樹B+樹的節點,數據庫I/O操做的最小單位是頁,與數據庫相關的內容都會存儲在頁的結構裏。數據庫
B+樹索引結構
- 在一棵B+樹中,每一個節點爲都是一個頁,每次新建節點的時候,就會申請一個頁空間
- 同一層的節點爲之間,經過頁的結構構成了一個雙向鏈表
- 非葉子節點爲,包括了多個索引行,每一個索引行裏存儲索引鍵和指向下一層頁面的指針
- 葉子節點爲,存儲了關鍵字和行記錄,在節點內部(也就是頁結構的內部)記錄之間是一個單向的表
B+樹頁節點結構
有如下幾個特色性能
- 將全部的記錄分紅幾個組, 每組會存儲多條記錄,
- 頁目錄存儲的是槽(slot),槽至關於分組記錄的索引,每一個槽指針指向了不一樣組的最後一個記錄
- 咱們經過槽定位到組,再查看組中的記錄
頁的主要做用是存儲記錄,在頁中記錄以單鏈表的形式進行存儲。
單鏈表優勢是插入、刪除方便,缺點是檢索效率不高,最壞的狀況要遍歷鏈表全部的節點。所以頁目錄中提供了二分查找的方式,來提升記錄的檢索效率。指針
B+樹的檢索過程
咱們再來看下B+樹的檢索過程blog
- 從B+樹的根開始,逐層找到葉子節點。
- 找到葉子節點爲對應的數據頁,將數據葉加載到內存中,經過頁目錄的槽採用二分查找的方式先找到一個粗略的記錄分組。
- 在分組中經過鏈表遍歷的方式進行記錄的查找。
爲何要用B+樹索引
數據庫訪問數據要經過頁,一個頁就是一個B+樹節點,訪問一個節點至關於一次I/O操做,因此越快能找到節點,查找性能越好。
B+樹的特色就是夠矮夠胖,能有效地減小訪問節點次數從而提升性能。索引
下面,咱們來對比一個二叉樹、多叉樹、B樹和B+樹。內存
二叉樹
二叉樹是一種二分查找樹,有很好的查找性能,至關於二分查找。
可是當N比較大的時候,樹的深度比較高。數據查詢的時間主要依賴於磁盤IO的次數,二叉樹深度越大,查找的次數越多,性能越差。
最壞的狀況是退化成了鏈表,以下圖
class
爲了讓二叉樹不至於退化成鏈表,人們發明了AVL樹(平衡二叉搜索樹):任何結點的左子樹和右子樹高度最多相差1效率
多叉樹
多叉樹就是節點能夠是M個,能有效地減小高度,高度變小後,節點變少I/O天然少,性能比二叉樹好了
B樹
B樹簡單地說就是多叉樹,每一個葉子會存儲數據,和指向下一個節點的指針。
例如要查找9,步驟以下
- 咱們與根節點的關鍵字 (17,35)進行比較,9 小於 17 那麼獲得指針 P1;
- 按照指針 P1 找到磁盤塊 2,關鍵字爲(8,12),由於 9 在 8 和 12 之間,因此咱們獲得指針 P2;
- 按照指針 P2 找到磁盤塊 6,關鍵字爲(9,10),而後咱們找到了關鍵字 9。
B+樹
B+樹是B樹的改進,簡單地說是:只有葉子節點才存數據,非葉子節點是存儲的指針;全部葉子節點構成一個有序鏈表
例如要查找關鍵字16,步驟以下
- 與根節點的關鍵字 (1,18,35) 進行比較,16 在 1 和 18 之間,獲得指針 P1(指向磁盤塊 2)
- 找到磁盤塊 2,關鍵字爲(1,8,14),由於 16 大於 14,因此獲得指針 P3(指向磁盤塊 7)
- 找到磁盤塊 7,關鍵字爲(14,16,17),而後咱們找到了關鍵字 16,因此能夠找到關鍵字 16 所對應的數據。
B+樹與B樹的不一樣:
- B+樹非葉子節點不存在數據只存索引,B樹非葉子節點存儲數據
- B+樹使用雙向鏈表串連全部葉子節點,區間查詢效率更高,由於全部數據都在B+樹的葉子節點,可是B樹則須要經過中序遍歷才能完成查詢範圍的查找。
- B+樹每次都必須查詢到葉子節點才能找到數據,而B樹查詢的數據可能不在葉子節點,也可能在,這樣就會形成查詢的效率的不穩定
- B+樹查詢效率更高,由於B+樹矮更胖,高度小,查詢產生的I/O最少。
這就是MySQL使用B+樹的緣由,就是這麼簡單!