B樹(B-Tree)的由來、數據結構、基本操作以及數據庫索引的應用


B樹是為磁盤存儲而專門設計的一類平衡搜索樹,B樹的高度僅隨着它所包含的節點數按對數增長,不過因為單個節點可以包含多個關鍵字,所以對數的底數可以比較大,實際應用中一般是50~2000,給個直觀的數字,一棵分支因子為1001、高度為2(不包含根節點)的B樹,可以存儲超過10億個關鍵字!

1.從磁盤結構講起

計算機的機械磁盤,為了攤還機械移動花費的等待時間,磁盤會一次存取多個數據項而不是一個,這樣的一次讀取的信息單元是page,我們可以用讀或寫的頁數作為磁盤存取總時間的主要近似值,在任何時刻,B樹算法都只需在內存中保持一定數量的頁面。B樹的設計考慮磁盤預讀取這點,一個B樹的節點通常和一個完整磁盤頁(page)一樣大,並且磁盤頁的大小限制了一個B樹節點可以含有的孩子個數(分支因子),當然這個具體也需要取決於一個關鍵字相對一頁的大小。B+ Tree中內部節點只存放關鍵字和孩子的指針,不存其他satellite information,因此最大化了內部節點的分支因子。

2.B樹的數據結構

typedef int KeyType;
#define m 3
struct
Node{ int keynum; /* 結點中關鍵字的個數,即結點的大小*/ struct Node *parent; /*指向parent結點*/ KeyType key[m]; /*關鍵字向量*/ struct Node *ptr[m]; /*子樹指針向量*/ };

3.B樹的查找

搜索一棵B樹和搜索一棵二叉搜索樹很相似,只是在每個節點所做的不是二叉或者“兩路”分支選擇,而是根據根節點的孩子數做多路分支選擇。

4.B樹的插入

B樹插入的時候都是插入到葉節點上,插入的時候會從根節點開始順着葉節點的方向沿途,如果遇到一個滿節點(該節點上的關鍵字達到2t-1,t代表t階B樹),就會split該節點,分裂節點方式就是把滿節點上的中間關鍵字往根節點方向提,分裂是樹長高的唯一途徑。B樹的每個葉節點具有相同的高度,所以B樹高度的增加發生在頂部而不是底部。插入節點的時候,從根的方向往下判斷,如果不是葉子節點,則必須選擇適當的葉子節點插入,因為在沿途已經分裂了節點,所以保證不會在滿節點上再插入節點。

5.B樹的刪除

和插入關鍵字類似,插入關鍵字的時候要保證節點不會太大,而且有可能會增高B樹。刪除節點的時候要保證一個節點不會變得太小,因為B樹的節點上的關鍵字有下界要求(除了根節點以外的每個內部節點至少有t個孩子,如果樹非空,根節點上至少有一個關鍵字),刪除關鍵字的時候如果在葉子節點,而且刪除之后還滿足B樹的要求,那直接刪除即可,不過如果是其他情況,比如在內部節點上刪除關鍵字,那就有一系列的算法分支需要考慮,感興趣的讀者可以自行找資料慢慢琢磨了。不過在實際場景中,由於一棵B樹中大部分關鍵字都在葉節點中,刪除操作最經常是從葉子節點中刪除關鍵字。

6.B樹的應用場景 

mysql的MyISAM和InnoDB兩個存儲引擎的索引實現方式:

  • MyISAM引擎使用B+ Tree作為索引結構,葉節點存放的是數據記錄的地址。
  • MyISAM引擎的輔助索引(二級索引)和主索引在結構上沒有區別,只是輔助索引的key可以重復,葉節點上存放的也是數據記錄的地址。
  • MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址。
  • InnoDB中表數據本身就是按B+ Tree組織的一個索引結構,葉節點存放的就不是數據記錄的地址,而是完整的數據記錄。所以InnoDB這種存儲方式,又稱為聚集索引,使得按主鍵的搜索十分高效,但二級索引搜索需要檢索兩遍索引:首先二級索引獲得主鍵,然后用主鍵到主索引中檢索到數據記錄。
  • 因為主鍵是InnoDB表記錄的”邏輯地址“,所以InnoDB要求表必須有主鍵,MyISAM可以沒有。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM