索引是關聯式資料庫效能調校的核心槓桿。本文以 200 萬筆實測數據為背景,系統闡述 MySQL 索引類型、建立語法、組合索引最左前綴原則、優化檢查清單與常見反模式。
article:200 萬列、定長結構 (id PK、title VARCHAR、content TEXT、time INT)。SELECT id, FROM_UNIXTIME(time) FROM article WHERE title = 'PHP筆試題...'INDEX idx_title (title) 後:< 0.01 秒。| 類型 | 特點 | 建立語法 |
|---|---|---|
| 一般索引 | 無限制,允許 NULL、重複值 | CREATE INDEX idx_name ON tbl(col(len));ALTER TABLE tbl ADD INDEX idx_name (col(len)); |
| 唯一索引 | 值必須唯一,允許 NULL | CREATE UNIQUE INDEX uk_name ON tbl(col(len));ALTER TABLE tbl ADD UNIQUE uk_name (col(len)); |
| 主鍵 | 唯一 + NOT NULL,隱含叢集索引 | PRIMARY KEY (col) (建表時) / ALTER TABLE tbl ADD PRIMARY KEY (col); |
| 全文索引 | MyISAM 專用 (5.6+ InnoDB 支援),針對長文本搜尋 | CREATE FULLTEXT INDEX ft_content ON tbl(content);ALTER TABLE tbl ADD FULLTEXT ft_content (content); |
| 組合索引 | 多欄位組合,遵循最左前綴 | CREATE INDEX idx_a_b ON tbl(a(len), b(len)); |
組合索引 (a, b, c) 實際可服務的查詢模式:
WHERE a = ?WHERE a = ? AND b = ?WHERE a = ? AND b = ? AND c = ?WHERE b = ? (非最左)WHERE c = ?WHERE a = ? AND c = ? (中間斷裂)本質:B+ 樹索引按 (a, b, c) 排序,查詢必須從最左欄位開始連續匹配才能利用索引定位。
VARCHAR(255) 前 10-20 字元唯一性高時,用 col(10) 節省空間與 I/O。WHERE YEAR(dt) = 2023 → 失效;改 WHERE dt >= '2023-01-01' AND dt < '2024-01-01'。LIKE 'abc%' 可用索引;LIKE '%abc%' 全表掃描。ORDER BY col 若無索引會觸發 Filesort。SELECT a, b FROM tbl WHERE c = ? → 建 INDEX idx_c_ab (c, a, b),查詢只掃索引不回表。| 操作 | 聚集索引 | 非聚集索引 |
|---|---|---|
| 範圍查詢 | ✅ 極佳 | ❌ |
| 單點查詢 | ✅ | ✅ 極佳 |
| 頻繁更新索引欄 | ❌ (頁分裂嚴重) | ✅ |
| 主鍵 | ✅ (預設) | |
| 外鍵 | ✅ | ✅ |
TEXT/BLOB 全長建索引 → 體積龐大、維護成本高,改用前綴或全文索引。WHERE col + 1 = 100 等運算導致索引失效。EXPLAIN 驗證,上線後才發現全表掃描。