圖解:什麼是 B+樹 ? (查找篇)

前面談了 B+樹的基本概念,今日主要說一下 B+樹的查找操作。

下面所有的查找操作都是在上面這顆 B+樹上進行了,爲此,我們先仔細觀察一下這顆B+樹(毫不隱瞞,這顆 B+樹出自於嚴蔚敏老師的數據結構教材)。

第一點:B+樹中的所有數據均保存在葉子結點,且根結點和內部結點均只是充當控制查找記錄的媒介,並不代表數據本身,所有的內部結點元素都同時存在於子結點中,是子節點元素中是最大(或最小)元素。

比如 B+ 樹中的結點 59 (結點 15、44、97、72 類似),是其子結點 [15、44、59] 中的最大元素,也是葉子結點 [51、59] 中的最大元素。所有的數據 [10、15、21、37、44、51、59、63、72、85、91、97] 均保存在葉子結點之中,而根結點 [59、97] 及內部結點 [15、44、59][72、97] 均不是數據本身,只是充當控制查找記錄的媒介。

需要注意的是,根結點的最大元素 97 是整顆 B+樹當中最大的元素,無論之後在葉子結點中插入或刪除多少元素,始終要保證最大元素在根結點當中,這個講插入和刪除時還會看到。

第二點:每一個葉子結點都有指向下一個葉子結點的 指針,便捷之處就在於之後我們將看到的區間查找。

查詢單個元素

我們以查詢 59 爲例進行說明。

第一次磁盤 I/O :訪問根結點 [59、97] ,發現 59 小於等於  [59、97] 中的 59 ,則訪問根結點的第一個孩子結點。

第二次磁盤 I/O : 訪問結點 [15、44、59] ,發現 59 大於 44 且小於等於 59 ,則訪問當前結點的第三個孩子結點 [51、59] .

第三次磁盤 I/O :訪問葉子結點 [51、59] ,順序遍歷結點內部,找到要查找的元素 59 .

我想你已經注意到了和 B-樹的區別,對於 B+樹中單個元素的查找而言,每一個元素都有相同的磁盤 I/O操作次數,即使查詢的元素出現在根結點中,但那只是一個充當控制查找記錄的媒介,並不是數據本身,數據真正存在於葉子結點當中,所以 B+樹中查找任何一個元素都要從根結點一直走到葉子結點纔可以。

B+樹的非葉子結點均不存儲 Data (即 ,官方將其稱爲衛星數據) ,所以與 B-樹相比,同樣大小的磁盤頁,B+樹的非葉子結點可以存儲更多的索引(關鍵字),這也就意味着在數據量相同的情況下,B+樹的結構比 B-樹更加 “矮胖”,查詢時磁盤 I/O 次數會更少。

注意: B-樹的查詢性能並不穩定,對於根結點中關鍵字可能只有一次磁盤 I/O,而對於葉子結點中的關鍵字需要樹的高度次磁盤 I/O 操作。

比如查找上圖 B-樹中的關鍵字 59 僅需要一次磁盤 I/O 操作,關鍵字 21 需要 3 次磁盤 I/O,關鍵字 72 需要 2 次磁盤 I/O.

B+樹所有查詢所有關鍵字的磁盤 I/O 的次數都是樹的高度。

區間查詢

爲了更清楚地看到 B+樹進行區間查詢的優勢,我們以查詢下面的 B-樹中大於等於21 ,小於等於63的關鍵字爲例進行說明。

第一步:訪問 B-樹的根結點 [59] ,發現 2159 小,則訪問根結點的第一個孩子 [15、44] .

第二步:訪問結點  [15、44] ,發現 21 大於 15 且小於 44 ,則訪問當前結點的第二個孩子結點 [21、37]

第三步:訪問結點 [21、37] , 找到區間的左端點 21 ,然後從該關鍵字 21 開始,進行中序遍歷,依次爲關鍵字 37 、44、51、59,直到遍歷到區間的右端點 63 爲止, 不考慮中序遍歷過程的壓棧和入棧操作,磁盤 I/O 次數多了 2次,即訪問結點 72 和結點 63 並加載進內存。

而 B+樹進行區間查找,簡直要舒服的不要不要的。同樣是查找區間 [21,63] 之間的關鍵字。

第一步:訪問根結點 [59、97] , 發現區間的左端點 21 小於 59, 則訪問第一個孩子結點 [15、44、59] .

第二步:訪問結點 [15、44、59]  ,發現 21 大於 15 且小於 44 ,則訪問第二個孩子結點 [21、37,44] .

第三步:訪問結點 [21、37,44]  ,找到了左端點 21 ,此時 B+樹的優越性就出來了,不再需要中序遍歷,而是相當於單鏈表的遍歷,直接從左端點 21 開始一直遍歷到左端點 63 即可,沒有任何額外的磁盤 I/O 操作。

綜合來看 B+樹的優勢就是:

  1. 查找時磁盤 I/O 次數更少,因爲 B+樹的非葉子結點可以存儲更多的關鍵字,數據量相同的情況下,B+樹更加 “矮胖” ,效率更高。

  2. B+樹查詢所有關鍵字的磁盤 I/O 次數都一樣,查詢效率穩定。

  3. B+樹進行區間查找時更加簡便實用。

此外給大家推薦一篇博文 MySQL索引背後的數據結構及算法原理(http://blog.codinglabs.org/articles/theory-of-mysql-index.html) ,其中對於MySQL 索引爲什麼採用 B+樹,以及InnoDB表爲什麼必須有主鍵,並且爲什麼推薦使用自增主鍵都有解釋,需要的朋友可以自提,我就不再造輪子了。

推薦閱讀:

圖解:什麼是B樹(心中有 B樹,做人要謙虛)?

你有 “Mojito” ,我有 B+樹!(概念篇)

作者:景禹,一個求極致的共享主義者,想帶你一起擁有更美好的生活,化作你的一把傘。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章