索引是資料庫效能調校的核心。許多開發者知道「加索引能加速查詢」,但對於索引在磁碟上如何組織、聯合索引的排序規則、以及為什麼「最左前綴」原則至關重要,往往只知其一不知其二。本文將透過模擬資料與圖解,直觀展示 MySQL(MyISAM 引擎)建立索引前後的資料排序變化,帶你窺探 B+ 樹葉子節點的真實面貌。
我們準備一張含 4 個欄位(id、a、b、c)共 21 筆資料的表。為了觀察索引建立後的排序效果,特意將主鍵 id 打亂後再按 1–27 排序,確保原始資料非天然有序。

a 後的排序變化建立 INDEX idx_a (a) 後,MySQL 會另闢一個 B+ 樹結構,葉子節點依 a 欄位值排序;a 值相同時,再按主鍵 id 遞增排序。新的葉子節點順序(以 id 代表該行)如下:
1 3 5 6 9 16 18 23 26 2 10 11 12 13 14 15 20 25 4 7 8 17 19 21 22 24 27

關鍵觀察: 同樣 a=1.1 的行,其 id 為 1、3、5、6… 依主鍵順序排列。這印證了「非唯一索引的葉子節點 = 索引鍵值 + 主鍵值」的結構。
(a,b) 的排序規則建立 INDEX idx_ab (a,b) 後,排序規則變為:先按 a 排序,a 相同再按 b 排序,最後才是 id。葉子節點順序:
6 18 23 10 15 20 7 22 27 1 3 26 2 11 25 4 8 24 5 9 16 12 13 14 17 19 21

同樣 a=1.1, b=2.1 的三行(id 18、6、23),最終按 id 6、18、23 排序。這正是「最左前綴」原則的物理體現:索引鍵值為 (a,b) 的元組,按字典序排列。
(a,b,c) 進階演示繼續建立 INDEX idx_abc (a,b,c),排序依據再延伸至 c 欄位。葉子節點順序:
23 6 18 15 20 10 27 22 7 1 26 3 11 2 25 24 4 8 5 16 9 12 14 13 17 19 21

可以看到,idx_abc 的葉子節點順序包含了 idx_ab 與 idx_a 的排序特性,這也是為什麼擁有 (a,b,c) 索引時,單獨建立 (a,b) 或 (a) 通常是多餘的。

id 遞增存放(聚簇索引特性)。(a,b,c) 涵蓋 (a,b) 與 (a) 的查詢需求,避免重複建立索引造成寫入開銷。id 排序,保證回表查詢的確定性。每次 INSERT/DELETE/UPDATE 索引欄位時,MySQL 必須同步維護所有相關 B+ 樹,將新記錄插入適當位置、分裂/合併頁面。當單表超過 500 萬行且索引過多時,維護成本會明顯拖慢寫入速度。因此:
WHERE、JOIN、ORDER BY 欄位建索引。ANALYZE TABLE 更新統計資訊,讓優化器做出正確選擇。理解索引的物理存儲結構,是從「會用索引」進階到「懂索引調優」的關鍵一步。希望這組圖解能幫你建立清晰的心智模型。