MySQL InnoDB 存儲引擎採用 B+ 樹作為索引數據結構。理解 B 樹與 B+ 樹的差異,是掌握索引原理、優化查詢效能的基石。本文通過結構對比、優缺點分析、InnoDB 實際應用三個維度深度解析。
| 特性 | B 樹 | B+ 樹 |
|---|---|---|
| 數據存儲位置 | 所有節點 (內部節點 + 葉子節點) 均存儲數據指針 (RowID) | 僅葉子節點存儲數據指針,內部節點僅存儲索引鍵值 |
| 葉子節點連結 | 無連結,獨立 | 所有葉子節點通過雙向鏈表串聯 |
| 索引鍵重複 | 內部節點出現的鍵值不再出現在葉子節點 | 內部節點鍵值在葉子節點全部重複出現 (冗餘索引) |
| 查找路徑 | 可能在內部節點命中,提前結束 | 必須走到葉子節點才能獲取數據 |
SELECT * FROM t WHERE id > 100 只需定位到 100 所在葉子頁,然後沿鏈表向右遍歷,無需回溯內部節點。B 樹需中序遍歷,頻繁上下跳轉。-- 聚簇索引 (主鍵索引) 葉子頁 +------------------+------------------+------------------+ | Page Header | Records (完整行) | Page Directory | | (鏈表指針、LSN) | (按主鍵有序) | (稀疏索引) | +------------------+------------------+------------------+ ↑ prev leaf next leaf ↑ (雙向鏈表) -- 二級索引 葉子頁 +------------------+------------------+------------------+ | Page Header | Records (索引列+主鍵) | Page Directory | +------------------+------------------+------------------+ ↑ prev leaf next leaf ↑
INDEX (a,b,c) 讓 SELECT a,b FROM t WHERE a=1 僅讀索引頁。WHERE id BETWEEN 100 AND 200 自動走葉子鏈表掃描。innodb_fill_factor (MySQL 8.0+) 預留空間減少頁分裂。B+ 樹通過 內外節點分工 (內部導航、葉子存儲+鏈表) 和 冗餘索引鍵,換取了更低的樹高、極致的範圍查詢效能、穩定的查詢延遲,完美契合關係型資料庫「範圍查詢多、順序讀多、覆蓋索引需求大」的負載特徵,成為 InnoDB、PostgreSQL、Oracle、SQL Server 等主流引擎的首選索引結構。