B樹的結構及效率

4.3 B樹
雖然一級或兩級索引一般有助於加快查詢,但在商用系統中常使用一種更通用的結構。這
一通用的數據結構簇稱爲B樹,而最常使用的變體稱爲B +樹。實質上:
? B樹能自動地保持與數據文件大小相適應的索引層次。
? 對所使用的存儲塊空間進行管理,使每一個塊的充滿程度在半滿與全滿之間。這樣的索引不
再須要溢出塊。
在接下來的內容中,咱們將討論「 B樹」,但具體細節都針對B +樹這一變體。其餘類型的B
樹在習題中討論。
4.3.1 B樹的結構
正如其名稱所暗示的那樣, B樹把它的存儲塊組織成一棵樹。這棵樹是平衡的,即從樹根到
樹葉的全部路徑都同樣長。一般B樹有三層:根、中間層和葉,但也能夠是任意多層。爲了對B
樹有一個直觀的印象,能夠先看一下圖4 - 2 一、圖4 - 2 2和圖4 - 2 3,其中前兩個圖所示的爲B樹結點,
然後一個圖所示的爲一個小而完整的B樹。
數據庫

對應於每一個B樹索引都有一個參數n,它決定了B樹的全部存儲塊的佈局。每一個存儲塊存放n
個查找鍵值和n+ 1個指針。在某種意義上講, B樹的存儲塊相似於4 . 1節講述的索引塊,只不過B
樹的塊除了有n個鍵-指針對外,還有一個額外的指針。在存儲塊能容納n個鍵和n+ 1個指針的前
提下,咱們把n取得儘量大。
例4 . 1 9 假定咱們的存儲塊大小爲4 0 9 6字節,且整數型鍵值佔4字節,指針佔8字節。要是不
考慮存儲塊塊頭信息所佔空間,那麼咱們但願找到知足4n+ 8 (n+ 1 )≤4 0 9 6的最大整數值n。這個
值是n = 340
。□緩存

(注:innodb默認的索引頁大小是16k,能夠算出n是1364.)數據結構


下面幾個重要的規則限制B樹的存儲塊中能出現的東西:
? 根結點中至少有兩個指針被使用。全部指針指向位於B樹下一層的存儲塊。
? 葉結點中,最後一個指針指向它右邊的下一個葉結點存儲塊,即指向下一個鍵值大於它的
塊。在葉塊的其餘n個指針當中,至少有個指針被使用且指向數據記錄;未使用
的指針可看做空指針且不指向任何地方。若是第i個指數被使用,則指向具備第i個鍵值的
記錄。
? 在內層結點中,全部的n+ 1個指針均可以用來指向B樹中下一層的塊。其中至少
個指針被實際使用(但若是是根結點,則無論n多大都只要求至少兩個指針被使用)。若是j
個指針被使用,那該塊中將有j-1個鍵,設爲K1,K2??,Kj - 1。第一個指針指向B樹的一
部分,一些鍵值小於K1的記錄可在這一部分找到。第二個指針指向B樹的另外一部分,全部
鍵值大小等於K1且小於K2的記錄可在這一部分中。依此類推。最後,第j個指針指向B樹的
又一部分,一些鍵值大於等於Kj - 1的記錄能夠在這一部分中找到。注意:某些鍵值遠小於
K1或遠大於Kj - 1的記錄可能根本沒法經過該塊到達,但可經過同一層的其餘塊到達。
? 倘若咱們以常規的畫樹方式來畫B樹,任一給定結點的子結點按從左(第一個子結點)到
右(最後一個子結點)的順序排列。那麼,咱們在任何一個層次上從左到右來看B樹的結
點,結點的鍵值將按非減的順序出現。
佈局


從技術上來說,整個B樹的塊只有一個指針也是可能的,由於它多是隻有一個記錄的數據文件的索引。在這種
狀況下,整個B樹既是根塊又是葉塊,且這個塊只有一個鍵值和一個指針。在下面的描述中咱們忽略這種平凡的
狀況。spa


例4 . 2 0 在這個例子和其餘B樹實例中,咱們設n= 3。也就是說,塊中可存放3個鍵值和4個
指針,這是一個不表明一般狀況的小數字。鍵值爲整數。圖4 - 2 1所示爲一個徹底使用的葉結點。
其中有三個鍵值5 七、8 1和9 5。前三個指針指向具備這些鍵值的記錄。而最後一個指針,指向右
邊鍵值大於它的下一個葉結點,這正是葉結點中一般的狀況。若是該葉結點是序列中的最後一
個,則該指針爲空。
葉結點沒必要所有充滿,但在咱們這個例子中, n= 3,故葉結點至少要有兩個鍵-指針對。也
就是說,圖4 - 2 1中的鍵值9 5和第三個指針能夠沒有,該指針標有「至鍵值爲9 5的記錄」。
指針


圖4 - 2 2所示爲一個典型的內部結點。其中有三個鍵值,與咱們在葉結點的例子中所選的同樣:
5 七、8 1和9 5 。該結點中還有四個指針。第一個指針指向B樹的一部分,經過它咱們只能到達鍵
值小於第一個鍵值即5 7的那些記錄。第二個指針通向鍵值介於該B樹塊第一個鍵值和第二個鍵值
之間的那些記錄,第三個指針對應鍵值介於該塊第二個鍵值和第三個鍵值之間的那些記錄,第
四個指針將咱們引向鍵值大於該塊中第三個鍵值的那些記錄。
同葉結點的例子同樣,內部結點的鍵和指針槽也沒有必要所有佔用。不過,當n= 3時,一個
內部結點至少要出現一個鍵和兩個指針。元素缺失最極端的情形就是鍵值只有5 7,而指針也僅
使用前兩個,在這種狀況下,第一個指針對應於小於5 7的鍵值,而第二個指針對應於大於等於
5 7的鍵值。鍵值□orm


例4 . 2 1 圖4 - 2 3所示爲一棵完整的三層B +樹;其中使用例4 . 2 0中所描述的結點。咱們假定
數據文件的記錄的鍵是2~4 7之間的全部素數。注意,這些值在葉結點中按順序出現一次。全部
葉結點都有兩個或3個鍵-指針對,還有一個指向序列中下一葉結點的指針。當咱們從左到右去
看葉結點時,全部鍵都是排好序的。
根結點僅有兩個指針,剛好是容許的最小數目,儘管至多可有4個指針。根結點中的某個鍵
將經過第一個指針訪問到的鍵值與經過第二個指針訪問到的鍵值分隔開來。也就是說,不超過
1 2的鍵值可經過根結點的第一個子樹找到;大於等於1 3的鍵值可經過第二個子樹找到。索引


雖然鍵值同樣,但圖4 - 2 1所示的葉結點與圖4 - 2 2所示的內部結點之間並無什麼聯繫。事實上,它們不可能出現
在同一棵B樹中。
記住本節討論的全部B樹都是B+樹,但在之後提到時咱們將省略「+」號。
it

 

 

4.3.7 B樹的效率
B樹使咱們能實現記錄的查找、插入和刪除,而每一個文件操做只需不多的磁盤I / O。首先我
們注意到,若是每一個塊容納的鍵數n至關大,好比1 0或更大,那麼,分裂或合併塊的狀況將會很
少。此外,這種操做必需時,絕大多數時候都被侷限在葉結點,所以只有兩個葉結點和它們的
父結點受到影響。因此,咱們基本上能夠忽略B樹重組的I / O開銷。
然而,每次按給定查找鍵值查找記錄都須要咱們從根結點一直訪問到葉結點以找到指向記
錄的指針。由於咱們只讀B樹的塊,因此磁盤I / O數將是B樹的層數加上一次(對查找而言)或兩
次(對插入或刪除而言)處理記錄自己的磁盤I / O。咱們確定會這樣問: B樹到底有多少層?對
於典型的鍵、指針和塊大小來講,三層就足夠了,除非數據庫極大。所以,咱們通常取3做爲B
樹的層數。下面的例子說明了其緣由。innodb


例4 . 2 7 回憶一下咱們在例4 . 1 9中的分析,咱們當時肯定每塊可容納示例數據的3 4 0個鍵-指
針對。倘若通常的塊充滿度介於最大和最小中間,即通常的塊有2 5 5個指針。一個根結點,有
2 5 5個子結點,有2 5 52= 6 5 0 2 5個葉結點;在這些葉結點中,咱們能夠有2 5 5的立方,即約1 . 6 6×1 0的7次方個指向記錄的指針。也就是說,記錄數小於等於1 . 6 6×1 0的7次方 (一千六百萬行)文件均可以被3層的B樹容納。□

(注:在innodb中,低於1/2就會合並,因此若是按(1364/2)的來算,3層的B樹在innodb中至少可容納682的3次方約合 31.72千萬行記錄的鍵)


不過,對於每次查找,咱們甚至能夠經過B樹用比3次還少的磁盤I / O來實現。B樹根結點塊
是永久地緩存在主存中的絕佳選擇。若是這樣,那麼每次查找3層的B樹只需兩次磁盤讀操做。
實際上,在某些狀況下,把B樹的第二層結點塊保存在緩衝區中也是合理的。這樣, B樹的查找
就減小到一次磁盤I / O再加上處理數據文件自己所需的磁盤I / O。

若是咱們看根結點的第一個具備鍵值7的子結點,會發現它有兩個指針,一個通向小於7的鍵,而另外一個通向大於等於7的鍵。注意,該結點的第二個指針只能使咱們找到鍵7和11,而非全部大於7的鍵,好比鍵1 3(雖然咱們能夠經過葉結點中指向下一個塊的指針找到那些更大的鍵)。最後,根結點的第二個子結點的4個指針槽都被使用。第一個指針將咱們引向一些鍵值小於2 3的鍵,即1 三、1 7和1 9。第二個指針將咱們引向鍵值大於等於2 3而小於3 1的全部鍵;第三個指針將咱們引向鍵值大於等於3 1而小於4 3的全部鍵;而第四個指針將咱們引向一些鍵值大於等於4 3的鍵(在這個例子中,是全部的鍵)。

相關文章
相關標籤/搜索