核心定義:主鍵索引
- 定義:
PRIMARY KEY,由一列或多列組成,唯一標識行,不允許 NULL,每張表**最多一個**。
- InnoDB 設計鐵律:
- 使用**無業務含義的自增整數** (BIGINT UNSIGNED)。
- 主鍵值**永不更新**,僅增刪。
- 拒絕動態類型(如
TIMESTAMP、UUID())。
- 收益:順序寫入減少頁分裂、避免主鍵更新導致的行遷移與碎片、提升範圍查詢與主鍵查找效能。
輔助索引體系
| 類型 | 別名 | 特點 | InnoDB 存儲差異 |
| 唯一索引 | Unique Key | 約束唯一性,允許單個 NULL | 葉子節點存主鍵值,回表查詢需二次查找 |
| 普通索引 | Secondary Key | 無唯一約束 | 同唯一索引,但查詢需繼續掃描確認是否還有匹配行 |
| 主鍵索引 | Primary Key | 聚簇索引,葉子節點存完整行數據 | **即表本身**,查詢無需回表 |
聚簇索引:InnoDB 的核心組織形式
概念
聚簇索引 = 索引鍵值邏輯順序決定物理存儲順序。InnoDB 表即 **Index-Organized Table (IOT)**,MyISAM 為 **Heap Organized Table (HOT)**。
選擇規則(優先級遞減)
- 顯式定義的
PRIMARY KEY。
- 首個 **不允許 NULL 的唯一索引**。
- 內部隱藏
ROWID (6 字節單調遞增)。
IOT vs HOT 優劣勢對比
| 維度 | InnoDB (IOT) | MyISAM (HOT) |
| 範圍查詢 | 極快(葉子節點鏈表順序讀取) | 需回表,隨機 IO 多 |
| 主鍵查找 | O(log N) 直接定位行數據 | O(log N) 定位指針 + 回表 |
| 頻繁更新非主鍵列 | 不移動行,僅修改頁內數據,碎片少 | 不移動行,但索引需維護指針 |
| 離散寫入 (UUID/隨機主鍵) | 頁分裂嚴重、碎片率高、寫入放大 | 僅追加寫入,無分裂問題 |
| 二級索引體積 | 葉子存主鍵值(隱含主鍵 6 字節),體積較大 | 葉子存行指針,體積較小 |
實測性能對比(100 萬行整數列隨機點查)
| 引擎/索引類型 | 相對效能 (主鍵=1.0) | 說明 |
| MyISAM 主鍵 / 不允許 NULL 的唯一索引 | 1.0 | 無本質差異 |
| MyISAM 普通索引 | 0.7 | 慢 30%+ |
| InnoDB 主鍵索引 | 1.0 | 基準 |
| InnoDB 唯一索引 | 0.91 | 需回表一次,慢 ~9% |
| InnoDB 普通索引 | 0.5 | 需回表 + 繼續掃描,慢 50%+ |
關鍵結論與選型建議
- InnoDB 表必須顯式定義自增主鍵,避免隱式 ROWID 導致的寫入熱點與二級索引膨脹。
- 主鍵即聚簇索引,聚簇索引不一定是主鍵(可為非空唯一索引),但**強烈建議一致**。
- MyISAM 無聚簇索引概念,主鍵與非空唯一索引本質等價,選型靈活。
- 業務主鍵 vs 代理主鍵:業務天然唯一且不變(如身份證號)可直用,否則堅持代理自增鍵。
- 覆蓋索引優化:InnoDB 二級索引葉子含主鍵值,查詢僅需索引列時可避免回表(
SELECT id FROM t WHERE idx_col=?)。
總結
理解 **主鍵索引、聚簇索引、二級索引** 在 InnoDB/MyISAM 中的物理存儲差異,是索引設計與 SQL 優化的基石。**自增整數主鍵 + 覆蓋索引** 是 InnoDB 高效能的核心模式;MyISAM 適合唯讀/歸檔場景,但生產核心業務**強制 InnoDB**。