首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> MySQL 資料庫 >> MySQL 綜合教學

MySQL 索引底層數據結構與算法原理(上):B+Tree 為何成為首選

     編輯:MySQL 綜合教學

MySQL 索引底層數據結構與算法原理(上):B+Tree 為何成為首選


索引的本質

MySQL 官方定義:索引是幫助 MySQL 高效獲取數據的數據結構。
核心:索引 = 數據結構。

數據庫通過維護滿足特定查找算法的額外數據結構(索引),引用(指向)實際數據,實現高級查找算法(如二分查找、B-Tree 查找)。

從二叉查找樹到 B-Tree

二叉查找樹查找復雜度 O(log2n),但數據庫幾乎不用,原因見下文磁盤存取原理分析。

B-Tree 定義

  • 度 d > 1,高度 h
  • 非葉節點:n-1 個 key,n 個指針,d ≤ n ≤ 2d
  • 葉節點:1~2d-1 個 key,指針為 null
  • 所有葉節點深度相同 = h
  • Key 非遞減排列,指針與 Key 間隔分布

B+Tree 改進

  • 節點指針上限 2d(而非 2d+1)
  • 內節點不存數據,僅存 Key;葉節點不存指針,存完整數據記錄
  • 葉節點通過鏈表指針串聯,支持高效範圍掃描

帶順序訪問指針的 B+Tree

葉節點增加相鄰葉節點指針,範圍查詢(如 key 18~49)只需定位到 18,然後順鏈表遍歷,極大提升區間查詢效率。

為什麼選 B-Tree/B+Tree?磁盤存取原理視角

主存 vs 磁盤

  • 主存(RAM):隨機訪問,時間與次數線性相關,無「距離」概念。
  • 磁盤:機械運動(尋道 + 旋轉),I/O 消耗比主存高數量級。

局部性原理與預讀

數據被訪問時,鄰近數據大概率即將被訪問。磁盤順序讀取極快(無尋道、少旋轉),因此預讀一頁(通常 4KB)載入內存,觸發缺頁中斷後程序繼續運行。

B-Tree 節點大小 = 一頁

數據庫設計將節點大小設置為一頁,每個節點一次 I/O 即可完全載入。新建節點直接申請一頁空間,利用頁對齊特性保證物理連續。

性能分析

  • B-Tree 查找最多 h-1 次 I/O(根節點常駐內存),復雜度 O(h) = O(logd N)。
  • 出度 d 通常 > 100,樹高 h 一般 ≤ 3。
  • 紅黑樹高度大得多,邏輯鄰近物理可能遠離,無法利用局部性,I/O 復雜度同級但常數項大得多。

B+Tree 更優

內節點無 data 域,dmax = floor(pagesize / (keysize + pointsize)) 更大,出度更大,樹高更矮,性能更強。

MySQL 存儲引擎索引實現差異

MyISAM:非聚集索引

  • 索引文件與數據文件分離。
  • B+Tree 葉節點 data 域存數據記錄地址。
  • 主索引要求 Key 唯一,輔助索引 Key 可重複,結構無差異。
  • 檢索:搜索索引 → 取地址 → 讀取數據文件。

InnoDB:聚集索引

  • 數據文件本身就是主索引(B+Tree),葉節點存完整數據記錄。
  • 主鍵即索引 Key,表必須有主鍵(無則自動生成 6 字節隱藏列)。
  • 輔助索引 data 域存主鍵值而非地址。
  • 輔助索引查找需回表:搜輔助索引得主鍵 → 回主索引取數據(兩次 B+Tree 查找)。

實戰優化啟示

  • 不建議過長字段做主鍵:所有輔助索引引用主鍵,主鍵過大導致輔助索引膨脹。
  • 避免非單調主鍵(UUID、隨機串):導致 B+Tree 頻繁分裂調整,插入性能極差。自增整數主鍵是最佳選擇。

下篇將深入討論高性能索引使用策略(覆蓋索引、最左前綴、索引下推等)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved