1. 程式人生 > >徹底搞懂MySQL為什麼要使用B+樹索引

徹底搞懂MySQL為什麼要使用B+樹索引

[toc] 搞懂這個問題之前,我們首先來看一下MySQL表的儲存結構,再分別對比二叉樹、多叉樹、B樹和B+樹的區別就都懂了。 # MySQL的儲存結構 ## 表儲存結構 ![](https://img2020.cnblogs.com/blog/662544/202101/662544-20210118214720036-361045515.png) >單位:表>段>區>頁>行 在資料庫中, 不論讀一行,還是讀多行,都是將這些行所在的頁進行載入。也就是說儲存空間的基本單位是頁。 一個頁就是一棵樹B+樹的節點,資料庫I/O操作的最小單位是頁,與資料庫相關的內容都會儲存在頁的結構裡。 ## B+樹索引結構 ![](https://img2020.cnblogs.com/blog/662544/202101/662544-20210118214743897-143699176.png) 1. 在一棵B+樹中,每個節點為都是一個頁,每次新建節點的時候,就會申請一個頁空間 2. 同一層的節點為之間,通過頁的結構構成了一個雙向連結串列 3. 非葉子節點為,包括了多個索引行,每個索引行裡儲存索引鍵和指向下一層頁面的指標 4. 葉子節點為,儲存了關鍵字和行記錄,在節點內部(也就是頁結構的內部)記錄之間是一個單向的表 ## B+樹頁節點結構 ![](https://img2020.cnblogs.com/blog/662544/202101/662544-20210118214750385-223445387.png) 有以下幾個特點 1. 將所有的記錄分成幾個組, 每組會儲存多條記錄, 2. 頁目錄儲存的是槽(slot),槽相當於分組記錄的索引,每個槽指標指向了不同組的最後一個記錄 3. 我們通過槽定位到組,再檢視組中的記錄 頁的主要作用是儲存記錄,在頁中記錄以單鏈表的形式進行儲存。 單鏈表優點是插入、刪除方便,缺點是檢索效率不高,最壞的情況要遍歷連結串列所有的節點。因此頁目錄中提供了二分查詢的方式,來提高記錄的檢索效率。 ## B+樹的檢索過程 我們再來看下B+樹的檢索過程 1. 從B+樹的根開始,逐層找到葉子節點。 2. 找到葉子節點為對應的資料頁,將資料葉載入到記憶體中,通過頁目錄的槽採用二分查詢的方式先找到一個粗略的記錄分組。 3. 在分組中通過連結串列遍歷的方式進行記錄的查詢。 # 為什麼要用B+樹索引 資料庫訪問資料要通過頁,一個頁就是一個B+樹節點,訪問一個節點相當於一次I/O操作,所以越快能找到節點,查詢效能越好。 B+樹的特點就是夠矮夠胖,能有效地減少訪問節點次數從而提高效能。 下面,我們來對比一個二叉樹、多叉樹、B樹和B+樹。 ## 二叉樹 ![](https://img2020.cnblogs.com/blog/662544/202101/662544-20210118214802439-1073803102.png) 二叉樹是一種二分查詢樹,有很好的查詢效能,相當於二分查詢。 但是當N比較大的時候,樹的深度比較高。資料查詢的時間主要依賴於磁碟IO的次數,二叉樹深度越大,查詢的次數越多,效能越差。 最壞的情況是退化成了連結串列,如下圖 ![](https://img2020.cnblogs.com/blog/662544/202101/662544-20210118214806601-2103838702.png) 為了讓二叉樹不至於退化成連結串列,人們發明了AVL樹(平衡二叉搜尋樹):任何結點的左子樹和右子樹高度最多相差1 ## 多叉樹 ![](https://img2020.cnblogs.com/blog/662544/202101/662544-20210118214833027-596391504.png) 多叉樹就是節點可以是M個,能有效地減少高度,高度變小後,節點變少I/O自然少,效能比二叉樹好了 ## B樹 ![](https://img2020.cnblogs.com/blog/662544/202101/662544-20210118214837245-1134854116.png) B樹簡單地說就是多叉樹,每個葉子會儲存資料,和指向下一個節點的指標。 例如要查詢9,步驟如下 1. 我們與根節點的關鍵字 (17,35)進行比較,9 小於 17 那麼得到指標 P1; 2. 按照指標 P1 找到磁碟塊 2,關鍵字為(8,12),因為 9 在 8 和 12 之間,所以我們得到指標 P2; 3. 按照指標 P2 找到磁碟塊 6,關鍵字為(9,10),然後我們找到了關鍵字 9。 ## B+樹 ![](https://img2020.cnblogs.com/blog/662544/202101/662544-20210118214843052-1544093189.png) B+樹是B樹的改進,簡單地說是:只有葉子節點才存資料,非葉子節點是儲存的指標;所有葉子節點構成一個有序連結串列 例如要查詢關鍵字16,步驟如下 1. 與根節點的關鍵字 (1,18,35) 進行比較,16 在 1 和 18 之間,得到指標 P1(指向磁碟塊 2) 2. 找到磁碟塊 2,關鍵字為(1,8,14),因為 16 大於 14,所以得到指標 P3(指向磁碟塊 7) 3. 找到磁碟塊 7,關鍵字為(14,16,17),然後我們找到了關鍵字 16,所以可以找到關鍵字 16 所對應的資料。 B+樹與B樹的不同: 1. B+樹非葉子節點不存在資料只存索引,B樹非葉子節點儲存資料 2. B+樹使用雙向連結串列串連所有葉子節點,區間查詢效率更高,因為所有資料都在B+樹的葉子節點,但是B樹則需要通過中序遍歷才能完成查詢範圍的查詢。 3. B+樹每次都必須查詢到葉子節點才能找到資料,而B樹查詢的資料可能不在葉子節點,也可能在,這樣就會造成查詢的效率的不穩定 4. B+樹查詢效率更高,因為B+樹矮更胖,高度小,查詢產生的I/O最少。 這就是MySQL使用B+樹的原因,就是這麼