索引是 MySQL 查詢性能的核心。本文系統梳理索引存儲結構、分類體系、創建語法、選擇策略、最左前綴原理、常見誤區,幫助開發者建立科學的索引設計思維。
| 類型 | 特點 | 創建語法 |
|---|---|---|
| 普通索引 | 無唯一性限制,最基礎 | CREATE INDEX idx_name ON tbl(col);ALTER TABLE tbl ADD INDEX idx_name (col); |
| 唯一索引 | 值不可重複,允許 NULL | CREATE UNIQUE INDEX idx_name ON tbl(col); |
| 主鍵 | 特殊唯一索引,非空、唯一、一表僅一個 | PRIMARY KEY (col) 建表時或 ALTER TABLE tbl ADD PRIMARY KEY (col); |
| 全文索引 | 5.6+ InnoDB 支持,專用於 MATCH...AGAINST | FULLTEXT INDEX idx_name (col); |
| 單列索引 | 單字段 | 同上 |
| 多列/聯合索引 | 多字段組合,遵循最左前綴 | CREATE INDEX idx_a_b_c ON tbl(a,b,c); |
對聯合索引 (a, b, c):
| WHERE 條件 | 是否用到索引 | 用到的索引列 |
|---|---|---|
a=1 AND b=2 AND c=3 | ✅ | a, b, c |
a=1 AND b=2 | ✅ | a, b |
a=1 | ✅ | a |
b=2 | ❌ | —(非最左列) |
a=1 AND c=3 | ⚠️ | a(c 斷層無法用) |
ORDER BY a, b | ✅ | a, b(避免 filesort) |
本質:B+Tree 索引按
(a, b, c)排序,只能從最左列開始連續匹配。
COUNT(DISTINCT col)/COUNT(*) > 0.1 才值得建索引INDEX idx_name (name(10)),節省空間、提升速度僅以下操作符可能觸發索引:
<, <=, =, >, >=, BETWEEN, IN, LIKE 'prefix%'
不走索引:LIKE '%suffix'、LIKE '%mid%'、函數包裹列 WHERE UPPER(col)='A'、隱式類型轉換 WHERE varchar_col = 123、OR 兩側索引不一致。
| 場景 | 問題 | 優化動作 |
|---|---|---|
| 查詢慢 | EXPLAIN 顯示 type=ALL | 添加 WHERE/JOIN 列索引 |
| 索引未命中 | 函數/運算在列上 | 改寫 SQL,移至常量側 |
| 聯表慢 | JOIN 列無索引/類型不一致 | 駆動表小、被驅動表 JOIN 列建索引、類型統一 |
| 排序慢 | Using filesort | 建立符合 ORDER BY 順序的聯合索引 |
| 分頁深 | LIMIT 100000, 10 | 延遲關聯/游標分頁/覆蓋索引 |
EXPLAIN 顯示 Using index,無需回表Using index conditionANALYZE TABLE 更新統計信息,防優化器誤判pt-online-schema-change 避免鎖表索引設計 = 業務查詢模式分析 + 數據分布統計 + 寫入性能權衡。無銀彈,只有持續觀測與調優。