1. 程式人生 > >B+Tree在資料庫索引上擁有獨特優勢的原因(為什麼比紅黑樹更合適)

B+Tree在資料庫索引上擁有獨特優勢的原因(為什麼比紅黑樹更合適)

二叉樹、平衡樹、紅黑樹等資料結構也可以用來實現索引,但是檔案系統及資料庫系統為什麼普遍採用B-/+Tree作為索引結構?

如果對B+Tree和B-Tree不太瞭解的同學可以先去看一下我的上一篇部落格,這樣對本文才能更好地瞭解(https://blog.csdn.net/qq_21993785/article/details/80576642)。

       在資料之外,資料庫系統還維護著滿足特定查詢演算法的資料結構,這些資料結構以某種方式引用(指向)資料,這樣就可以在這些資料結構上實現高階查詢演算法。這種資料結構,就是索引

B-Tree

B-Tree中的每個節點根據實際情況可以包含大量的關鍵字資訊和分支,如下圖所示為一個3階的B-Tree:



每個節點佔用一個盤塊的磁碟空間(也就是一頁,詳見上一篇部落格https://blog.csdn.net/qq_21993785/article/details/80576642),一個節點上有兩個升序排序的關鍵字(17、35)和三個指向子樹根節點的指標(p1、p2、p3),指標儲存的是子節點所在磁碟塊的地址。兩個關鍵詞劃分成的三個範圍域對應三個指標指向的子樹的資料的範圍域。以根節點為例,關鍵字為17和35,P1指標指向的子樹的資料範圍為小於17,P2指標指向的子樹的資料範圍為17~35,P3指標指向的子樹的資料範圍為大於35。

模擬查詢關鍵字29的過程:

  1. 根據根節點找到磁碟塊1,讀入記憶體。【磁碟I/O操作第1次】
  2. 比較關鍵字29在區間(17,35),找到磁碟塊1的指標P2。
  3. 根據P2指標找到磁碟塊3,讀入記憶體。【磁碟I/O操作第2次】
  4. 比較關鍵字29在區間(26,30),找到磁碟塊3的指標P2。
  5. 根據P2指標找到磁碟塊8,讀入記憶體。【磁碟I/O操作第3次】
  6. 在磁碟塊8中的關鍵字列表中找到關鍵字29。

分析上面過程,發現需要3次磁碟I/O操作,和3次記憶體查詢操作。由於記憶體中的關鍵字是一個有序表結構,可以利用二分法查詢提高效率。而3次磁碟I/O操作是影響整個B-Tree查詢效率的決定因素。B-Tree相對於AVLTree縮減了節點個數,使每次磁碟I/O取到記憶體的資料都發揮了作用,從而提高了查詢效率。

B+Tree

B-Tree有許多變種,其中最常見的是B+Tree,例如MySQL就普遍使用B+Tree實現其索引結構。

與B-Tree相比,B+Tree有以下不同點:

1. 每個節點的指標上限為2d而不是2d+1。

2. 內節點不儲存data,只儲存key;葉子節點不儲存指標。

由於B+Tree的非葉子節點只儲存鍵值資訊不再儲存data資料,所有的data資料均儲存在葉子節點中,這樣使得內節點出度d值會變得大,下面會對記憶體出度(出度越大越好)進行講解。假設每個磁碟塊能儲存4個鍵值及指標資訊,則變成B+Tree後其結構如下圖所示:


由於並不是所有節點都具有相同的域,因此B+Tree中葉節點和內節點一般大小不同。這點與B-Tree不同,雖然B-Tree中不同節點存放的key和指標可能數量不一致,但是每個節點的域和上限是一致的,所以在實現中B-Tree往往對每個節點申請同等大小的空間。

帶有順序訪問指標的B+Tree

一般在資料庫系統或檔案系統中使用的B+Tree結構都在經典B+Tree的基礎上進行了優化,增加了順序訪問指標。在B+Tree的每個葉子節點增加一個指向相鄰葉子節點的指標,就形成了帶有順序訪問指標的B+Tree。做這個優化的目的是為了提高區間訪問的效能,例如圖中如果要查詢key為從15到60的所有資料記錄,當找到15後,只需順著節點和指標順序遍歷就可以一次性訪問到所有資料節點,極大提到了區間查詢效率。

為什麼紅黑樹等資料結構也可以用來實現索引,但是檔案系統及資料庫系統普遍採用B-/+Tree作為索引結構

一般使用磁碟I/O次數評價索引結構的優劣。先從B-Tree分析,根據B-Tree的定義,可知檢索一次最多需要訪問h個節點。資料庫系統的設計者巧妙利用了磁碟預讀原理,將一個節點的大小設為等於一個頁,這樣每個節點只需要一次I/O就可以完全載入。為了達到這個目的,在實際實現B-Tree還需要使用如下技巧:

每次新建節點時,直接申請一個頁的空間,這樣就保證一個節點物理上也儲存在一個頁裡,加之計算機儲存分配都是按頁對齊的,就實現了一個node只需一次I/O。

B-Tree中一次檢索最多需要h-1次I/O(根節點常駐記憶體),漸進複雜度為O(h)=O(logdN)。一般實際應用中,出度d是非常大的數字,通常超過100,因此h非常小(通常不超過3)。

綜上所述,用B-Tree作為索引結構效率是非常高的。

而紅黑樹這種結構,h明顯要深的多。由於邏輯上很近的節點(父子)物理上可能很遠,無法利用區域性性,所以紅黑樹的I/O漸進複雜度也為O(h),效率明顯比B-Tree差很多。

上文還說過,B+Tree更適合外存索引,原因和內節點出度d有關。從上面分析可以看到,d越大索引的效能越好,而出度的上限取決於節點內key和data的大小:

dmax = floor(pagesize / (keysize + datasize + pointsize))   (pagesize – dmax >= pointsize)

dmax = floor(pagesize / (keysize + datasize + pointsize)) – 1   (pagesize – dmax < pointsize)

floor表示向下取整。由於B+Tree內節點去掉了data域,因此可以擁有更大的出度,擁有更好的效能

下一篇部落格將討論B+Tree是如何具體實現為MySQL中索引,同時將結合MyISAM和InnDB儲存引擎介紹非聚集索引和聚集索引兩種不同的索引實現形式。