聯合索引 KEY idx(a,b,c) 等價於建立三棵 B+ 樹的前綴:(a)、(a,b)、(a,b,c)。查詢**必須從最左列開始連續匹配**,中斷即停止使用索引。
| WHERE 條件 | 是否走索引 | 使用的索引列 |
|---|---|---|
a=1 | ✅ | a |
a=1 AND b=2 | ✅ | a,b |
a=1 AND b=2 AND c=3 | ✅ | a,b,c |
b=2 | ❌ | 全表掃描 |
b=2 AND c=3 | ❌ | 全表掃描 |
a=1 AND c=3 | ⚠️ 部分 | 僅用 a,c 為過濾條件 |
聯合索引定義列排序方向(ASC/DESC),ORDER BY **完全一致或完全相反** 時可消除 Filesort。
CREATE INDEX idx_example ON t (col1 ASC, col2 DESC, col3 ASC);
-- ✅ 消除 Filesort
ORDER BY col1 ASC, col2 DESC, col3 ASC; -- 同序
ORDER BY col1 DESC, col2 ASC, col3 DESC; -- 逆序
-- ❌ 觸發 Filesort
ORDER BY col1 ASC, col2 ASC, col3 ASC; -- col2 方向不一致
LIKE 'prefix%' 可用索引,LIKE '%suffix' 或 LIKE '%mid%' **不可用**。場景:SELECT id FROM articles WHERE category_id=? ORDER BY created DESC LIMIT 10(id 為主鍵)
| 引擎 | 推薦聯合索引 | 原理 |
|---|---|---|
| InnoDB | (category_id, created) | 二級索引葉子**自帶主鍵值**,直接覆蓋查詢,無需回表 |
| MyISAM | (category_id, created, id) | 二級索引葉子**僅存行指針**,需顯式包含 id 才能覆蓋 |
結論:InnoDB 天然支持主鍵回表優化,MyISAM 需手工構建覆蓋索引。
| 陷阱 | 示例 | 破解方案 |
|---|---|---|
| 不等於操作 | WHERE dept_id <> 1000 | 改寫 WHERE dept_id < 1000 OR dept_id > 1000 |
| IS NULL 判斷 | WHERE col IS NULL | 建表定義 NOT NULL DEFAULT '',或使用位圖索引 (外部引擎) |
| 函數/運算作用於索引列 | WHERE TRUNC(birthdate) = '...' | 改寫範圍查詢 WHERE birthdate >= '...' AND birthdate < '...'+1;或 8.0 函數索引 |
| 隱式類型轉換 | WHERE varchar_col = 123 | 統一使用字符串 WHERE varchar_col = '123' |
| OR 跨列未建聯合索引 | WHERE a=1 OR b=2 | 改寫 UNION ALL 或建立 (a,b)、(b,a) 雙索引 |
Cardinality / Rows < 20% 索引效用極低,僅增加寫入開銷,建議刪除。username),**優先使用 latin1 或 ascii**,索引體積比 utf8mb4 縮小 50%+,查詢更快。ORDER BY,消除 Filesort。ANALYZE TABLE 更新統計信息,配合 EXPLAIN 驗證執行計劃。Handler_read_next、Sort_merge_passes 指標,發現退化及時調整。聯合索引是「空間換時間」的藝術,**精準建模、持續觀測、動態調整**,方能在業務演進中保持查詢高效能。