標籤:nod src next 沒有 inf 條件 二叉尋找樹 儲存 拆分
MySQL 索引與 B+ 型樹狀結構B+ 型樹狀結構
MySQL Innodb 儲存引擎是使用 B+ 型樹狀結構來組織索引的。在介紹 B+ 型樹狀結構以前,先認識一下什麼是 B 樹,B 樹是平衡二叉樹,與一般的二叉尋找樹不同,平衡二叉樹首先滿足二叉尋找樹的定義(左子樹的鍵小於根的鍵,右子樹的鍵大於根的鍵),其次必須滿足任何節點的兩個子樹的高度最大差為 1。B 樹的維護要求插入和更新節點時,通過 1 次或多次左旋和右旋來滿足平衡的條件。二叉尋找樹是否平衡直接影響了尋找需要比較的次數。
B+ 型樹狀結構與普通的二叉樹不同,它的節點由多個關鍵字和指向子樹的指標組成,指向子樹的指標個數等於關鍵字個數加 1,這些子樹中關鍵字的範圍由它的父節點限定,真正的資料部分是存放在葉子節點中的。MySQL 中頁資料結構就是這些葉子節點,每個葉子節點對應了一個 Page,而 Page 的資料結構中有 PAGE_PREV 和 PAGE_NEXT 兩個指標,因此這些葉子節點兩兩之間也是相互串連的。
B+ 型樹狀結構的插入操作
由於 B+ 型樹狀結構需要在插入後依然保證平衡,因此插入操作會涉及到頁的拆分操作。Index Page 指的是非葉子結點而 Leaf Page 指的是葉子節點。插入操作分為以下三種情況:
- 當 Index Page 和 Leaf Page 都不滿時,直接將記錄插入到葉子節點中。
- 當 Index Page 不滿,Leaf Page 滿時,先將節點放入對應 Page,以中間節點作為依據,將 Page 拆分,然後將中間節點放入 Index Page 中,拆分後的左右記錄分別放在中間節點的左右兩邊。
- 當 Index Page 和 Leaf Page 都滿了,先拆分 Leaf Page,然後再拆分 Index Page,拆分 Index Page 的方法與拆分 Leaf Page 的方法一樣。
此處需要注意:為了在可能地情況下減少頁的拆分操作,B+ 型樹狀結構提供了類似二叉平衡樹的旋轉操作。旋轉操作發生在 Leaf Page 已經滿,但是其左右兄弟節點沒有滿的情況下。
B+ 型樹狀結構的刪除操作
B+ 型樹狀結構使用填滿因數來控制樹的變化,即中間節點關鍵字的數量和葉子節點關鍵字的數量和最大值的比例關係。此處以填滿因數為 50% 為例。小於填滿因數即為小於總容量的一半。刪除操作可以分為以下三種情況:
- 當 Leaf Page 關鍵字個數和 Index Page 節點關鍵字的個數都不小於填滿因數時,直接將記錄從 Leaf Node 中刪除,如果該節點為 Index Page 節點,那麼將 Index Page 節點替換為其右節點。
- 當 Leaf Page 關鍵字個數小於而 Index Page 不小於填滿因數時,將 Leaf Page 節點和其兄弟節點合并,同時更新 Index Page 節點。
- 當 Leaf Page 關鍵字個數和 Index Page 節點關鍵字的個數都小於填滿因數時,在情況 2 的基礎上還需要合并 Index Page 節點。
索引
索引在 MySQL 中就是使用 B+ 型樹狀結構實現的,不同索引之間形成的 B+ 型樹狀結構也是不同的。
叢集索引
叢集索引就是根據主鍵來構造 B+ 型樹狀結構,葉子節點存放對應頁的行記錄。
輔助索引(非叢集索引)
輔助索引就是使用非主鍵構造的 B+ 型樹狀結構,葉子節點存放的是對應的索引值以及相應的叢集索引鍵。通過輔助索引來搜尋一般是兩級的,第一級找到索引值對應的叢集索引鍵,第二級是根據叢集索引鍵尋找行記錄。
聯合索引
聯合索引就是對錶上的多個列進行索引,這樣構造的 B+ 型樹狀結構的 Index Node 和 Page Node 包含多個鍵。
索引覆蓋
在聯合索引的情況去搜尋行記錄,假設需要的行記錄的列正好包含在聯合索引中,那麼此時結果將可以直接從聯合索引中得到,省去了從叢集索引中搜尋,由於不包含整行的記錄所以可以大大減少 IO。
不使用索引的情況
當查詢滿足條件的行的所有列時,MySQL 不使用輔助索引,而是直接使用叢集索引。原因是即使使用了輔助索引,還是必須通過葉子節點中的目錄進行叢集索引的尋找,才能得到完整的資訊,那麼直接從叢集索引中擷取即可。
MySQL 索引與 B+ 型樹狀結構