【面試普通人VS高手系列】b樹和b+樹的理解

跟著Mic學架構發表於2022-04-20

資料結構與演算法問題,困擾了無數的小夥伴。

很多小夥伴對資料結構與演算法的認知有一個誤區,認為工作中沒有用到,為什麼面試要問,問了能解決實際問題?

圖靈獎獲得者: Niklaus Wirth 說過: 程式=資料結構+演算法, 也就說我們無時無刻都在和資料結構打交道。

只是作為Java開發,由於技術體系的成熟度較高,使得大部分人認為:程式應該等於 框架 + SQL 呀?

今天我們就來分析一道資料結構的題目:”B樹和B+樹“。

關於這個問題,我們來看看普通人和高手的回答!

普通人:

嗯. 我想想 … 嗯… Mysql裡面好像是用了B+樹來做索引的! 然後…

高手:

為了更清晰的解答這個問題,我打算從三個方面來回答:

  • 瞭解二叉樹、AVL樹、B樹的概念
  • B樹和B+樹的應用場景
  1. B樹是一種多路平衡查詢樹,為了更形象的理解。

二叉樹,每個節點支援兩個分支的樹結構,相比於單向連結串列,多了一個分支。

二叉查詢樹,在二叉樹的基礎上增加了一個規則,左子樹的所有節點的值都小於它的根節點,右子樹的所有子節點都大於它的根節點。

img

二叉查詢樹會出現斜樹問題,導致時間複雜度增加,因此又引入了一種平衡二叉樹,它具有二叉查詢樹的所有特點,同時增加了一個規則:”它的左右兩個子樹的高度差的絕對值不超過1“。平衡二叉樹會採用左旋、右旋的方式來實現平衡。

img

而B樹是一種多路平衡查詢樹,它滿足平衡二叉樹的規則,但是它可以有多個子樹,子樹的數量取決於關鍵字的數量,比如這個圖中根節點有兩個關鍵字3和5,那麼它能夠擁有的子路數量=關鍵字數+1。

因此從這個特徵來看,在儲存同樣資料量的情況下,平衡二叉樹的高度要大於B樹。

img

B+樹,其實是在B樹的基礎上做的增強,最大的區別有兩個:

    1. B樹的資料儲存在每個節點上,而B+樹中的資料是儲存在葉子節點,並且通過連結串列的方式把葉子節點中的資料進行連線。
    2. B+樹的子路數量等於關鍵字數

這個是B樹的儲存結構,從B樹上可以看到每個節點會儲存資料。

img

這個是B+樹,B+樹的所有資料是儲存在葉子節點,並且葉子節點的資料是用雙向連結串列關聯的。

img

2.B樹和B+樹,一般都是應用在檔案系統和資料庫系統中,用來減少磁碟IO帶來的效能損耗。

以Mysql中的InnoDB為例,當我們通過select語句去查詢一條資料時,InnoDB需要從磁碟上去讀取資料,這個過程會涉及到磁碟IO以及磁碟的隨機IO

img

我們知道磁碟IO的效能是特別低的,特別是隨機磁碟IO。

因為,磁碟IO的工作原理是,首先系統會把資料邏輯地址傳給磁碟,磁碟控制電路按照定址邏輯把邏輯地址翻譯成實體地址,也就是確定要讀取的資料在哪個磁軌,哪個扇區。

為了讀取這個扇區的資料,需要把磁頭放在這個扇區的上面,為了實現這一個點,磁碟會不斷旋轉,把目標扇區旋轉到磁頭下面,使得磁頭找到對應的磁軌,這裡涉及到尋道事件以及旋轉時間。

很明顯,磁碟IO這個過程的效能開銷是非常大的,特別是查詢的資料量比較多的情況下。

所以在InnoDB中,乾脆對儲存在磁碟塊上的資料建立一個索引,然後把索引資料以及索引列對應的磁碟地址,以B+樹的方式來儲存。

如圖所示,當我們需要查詢目標資料的時候,根據索引從B+樹中查詢目標資料即可,由於B+樹分路較多,所以只需要較少次數的磁碟IO就能查詢到。

img

3.為什麼用B樹或者B+樹來做索引結構?原因是AVL樹的高度要比B樹的高度要高,而高度就意味著磁碟IO的數量。所以為了減少磁碟IO的次數,檔案系統或者資料庫才會採用B樹或者B+樹。

以上就是我對B樹和B+樹的理解!

總結

資料結構在實際開發中非常常見,比如陣列、連結串列、雙向連結串列、紅黑樹、跳躍表、B樹、B+樹、佇列等。

在我看來,資料結構是程式設計中最重要的基本功之一。

學了順序表和連結串列,我們就能知道查詢操作比較多的場景中應該用順序表,修改操作比較多的場景應該使用連結串列。

學了佇列之後,就知道對於FIFO的場景中,應該使用佇列。

學了樹的結構後,會發現原來查詢類的場景,還可以更進一步提升查詢效能。

基本功決定大家在技術這個崗位上能夠走到的高度。

好的,本期的普通人VS高手面試系列就到這裡結束了,喜歡的朋友記得點贊收藏。

如果最近大家遇到一些場景類和方案設計類的問題,歡迎私信我,我在後續的內容中給大家做解答!

部分高手面試文件已整理,需要的小夥伴可以私信或者評論區留言。

img

相關文章