1. 程式人生 > 實用技巧 >InnoDB 中 B+ 樹索引的分裂

InnoDB 中 B+ 樹索引的分裂

資料庫中B+樹索引的分裂並不總是從頁的中間記錄開始,這樣可能會導致空間的浪費,例如下面的記錄:

1, 2, 3, 4, 5, 6, 7, 8, 9

插入式根據自增順序進行的,若這時插入10這條記錄後需要進行頁的分裂操作,那麼根據B+樹對半分裂的規則,會將記錄5作為分裂點記錄,分裂後得到下面兩個頁:

P1: 1, 2, 3, 4
P2: 5, 6, 7, 8, 9, 10

然而由於插入是順序的,P1這個頁中將不再會有記錄被插入,從而導致空間的浪費,而P2又會再次分裂。那麼如何優化?

InnoDB儲存引擎的Page Header有以下幾個部分用來儲存插入的順序資訊:

  • PAGE_LAST_INSERT
    :最後插入記錄的位置。
  • PAGE_DIRECTION:記錄插入的方向。假如新插入的一條記錄的主鍵值比上一條記錄的主鍵值大,我們說這條記錄的插入方向是右邊,反之則是左邊。用來表示最後一條記錄插入方向的狀態就是PAGE_DIRECTION
  • PAGE_N_DIRECTION:假設連續幾次插入新記錄的方向都是一致的,InnoDBhi把沿著同一個方向插入記錄的條數記下來,這個條數就用PAGE_N_DIRECTION這個狀態表示。當然,如果最後一條記錄的插入方向改變了的話,這個狀態的值會被清零重新統計。

通過這些資訊,InnoDB儲存引擎可以決定格式向左還是向右進行分裂,同時決定將分裂點記錄為哪一個。若插入是隨機的,則取頁的中間記錄作為分裂點的記錄,這和之前介紹的相同。若往同一方向進行插入的記錄條數為5

,並且目前已經定位到的記錄(InnoDB引擎插入時,首先需要進行定位,定位到的記錄為待插入記錄的前一條記錄)之後還有3條記錄,則分裂點的記錄為定位到的記錄後的第三條記錄,否則分裂點記錄就是待插入的記錄。(這裡的53是固定的,與具體例子無關)

來看一個向右分裂的例子,定位到的記錄之後還有3條記錄,則分裂點記錄如下圖所示:

以split record為分裂點記錄最終向右分裂得到下圖所示的情況:

對於下圖的情況,分裂點就為插入記錄本身,向右分裂後僅插入記錄本身,這在自增插入時是普遍存在的一種情況: