MySQL InnoDB 索引 (INDEX) 頁結構
InnoDB 為了不同的目的而設計了不同類型的頁,我們把用於存放記錄的頁叫做索引頁
索引頁內容
索引頁分為以下部分:
- File Header:表示頁的一些通用信息,占固定的38字節
- Page Header:表索引頁專有的一些信息,占固定的56個字節
- Infimum & Supremum:兩個虛擬的偽記錄,分別表示頁中的最小和最大記錄,占固定的26個字節
- User Records:真實存儲我們插入的記錄的部分,大小不固定
- Free Space:頁中尚未使用的部分,大小不固定
- Page Directory:頁中的某些記錄相對位置,也就是各個槽在頁面中的地址偏移量,大小不固定,插入的記錄越多,這個部分占用的空間越多
- File Trailer:用於檢驗頁是否完整的部分,占用固定的8個字節
文件頭部(File Header)
文件頭部各個類型的頁都有
包含以下部分:
名稱 | 大小 | 作用 |
---|---|---|
FIL_PAGE_SPACE_OR_CHKSUM | 4 | 頁的校驗和 (checksum) |
FIL_PAGE_OFFSET | 4 | 頁號 (每個頁的都不同) |
FIL_PAGE_PREV | 4 | 上一個頁的頁號 |
FIL_PAGE_NEXT | 4 | 下一個頁的頁號 |
FIL_PAGE_LSN | 8 | 頁面被最后修改時對應的日志序列位置 (Log Sequence Number) |
FIL_PAGE_TYPE | 2 | 該頁的類型 |
FIL_PAGE_FILE_FLUSH_LSN | 8 | 僅在系統表空間的一個頁中定義,代表文件至少被刷新到了對應的 LSN 值 |
FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID | 4 | 頁屬於哪個表空間 |
FIL_PAGE_PREV
和 FIL_PAGE_NEXT
代表上一頁和下一頁的頁碼,使得多個索引頁之間像雙向鏈表一樣連接起來
頁面頭部(Page Header)
頁面頭部索引頁特有的,記錄了當前頁面的狀態信息
包含以下部分:
名稱 | 大小 (byte) | 作用 |
---|---|---|
PAGE_N_DIR_SLOTS | 2 | 頁目錄中的槽數量 |
PAGE_HEAP_TOP | 2 | 還未使用的空間最小地址,也就是說從該地址之后就是 Free Space |
PAGE_N_HEAP | 2 | 本頁中的記錄的數量(包括最小和最大記錄以及標記為刪除的記錄) |
PAGE_FREE | 2 | 第一個已經標記為刪除的記錄地址(各個已刪除的記錄通過 next_record 也會組成一個單鏈表,這個單鏈表中的記錄可以被重新利用) |
PAGE_GARBAGE | 2 | 已刪除記錄占用的字節數 |
PAGE_LAST_INSERT | 2 | 最后插入記錄的位置 |
PAGE_DIRECTION | 2 | 記錄插入的方向 (新插入記錄的主鍵值比上一條記錄的主鍵值大,插入方向就是右邊,反之則是左邊) |
PAGE_N_DIRECTION | 2 | 一個方向連續插入的記錄數量 |
PAGE_N_RECS | 2 | 該頁中記錄的數量(不包括最小和最大記錄以及被標記為刪除的記錄) |
PAGE_MAX_TRX_ID | 8 | 修改當前頁的最大事務 ID,該值僅在二級索引中定義 |
PAGE_LEVEL | 2 | 當前頁在 B+ 樹中所處的層級 |
PAGE_INDEX_ID | 8 | 索引 ID,表示當前頁屬於哪個索引 |
PAGE_BTR_SEG_LEAF | 10 | B+ 樹葉子段的頭部信息,僅在 B+ 樹的 Root 頁定義 |
PAGE_BTR_SEG_TOP | 10 | B+ 樹非葉子段的頭部信息,僅在 B+ 樹的 Root 頁定義 |
最小記錄(Infimum) & 最大紀錄(Supremum)
兩個虛擬的行記錄,分別位於記錄鏈表的開頭和結尾
用戶記錄(User Records)
用戶記錄是按照相應行格式存儲數據的地方
MySQL 行格式 <- 點擊查看
記錄之間的連接
以 Compact 為例:
借助 next_record
,記錄之間像鏈表一樣連接起來,順序為主鍵從小到大排序,第一個為最小記錄,最后一條為最大紀錄
next_record
指向的是下一紀錄真數據開始的地方,也就是下一紀錄 next_record
之后
刪除記錄
當其中的一條記錄被刪除后,上一條記錄的 next_record
指向下一條紀錄,此記錄標記為刪除,next_record
指向 0,當前組最后一條記錄 n_owned
更新
頁目錄 (Page Directory)
頁目錄在靠近頁尾部的地方,記錄着每組記錄中最后一條記錄的地址偏移量,每個偏移量被放在槽 (Slot) 中
分組
最小記錄所在的分組只能有 1 條記錄,最大記錄所在的分組擁有的記錄條數只能在 1~8 條之間,剩下的分組中記錄的條數范圍只能在是 4~8 條之間
n_owned
表示當前組中一共有幾條記錄
查找
由於頁目錄中記錄的主鍵是有順序的,所以可以通過二分法進行查找
通過二分法在頁目錄找到對應的槽,再遍歷整個組中的記錄
File Trailer
用於確認內存同步到磁盤是否完整
分為兩部分:
前 4 個字節:校驗和
當一個頁面在內存中修改之后,在同步之前需要先計算出校驗和
File Header 在頁面的前面,所以校驗和會先進行同步,File Trialer 在最后進行同步,如果兩次校驗和不同說明數據改變了
后 4 個字節:LSN
總結
索引頁之間的連接
各個索引頁可以按照頁中最小主鍵值從小到大組成一個雙向鏈表,每個索引頁中的記錄又會按照主鍵值從小到大組成一個單鏈表