表 mytable(id, username) 1 萬筆資料,查 username='admin':
| 類型 | 特點 | 建立語法範例 |
|---|---|---|
| 普通索引 | 無限制,允許 NULL | CREATE INDEX idx_name ON t(name(10));ALTER TABLE t ADD INDEX idx_name (name(10)); |
| 唯一索引 | 值唯一,允許 NULL | CREATE UNIQUE INDEX uk_email ON t(email); |
| 主鍵索引 | 唯一+非空,一表僅一個 | CREATE TABLE t (id INT PRIMARY KEY AUTO_INCREMENT); |
| 組合索引 | 多欄位組合,遵循最左前綴 | ALTER TABLE t ADD INDEX idx_name_city_age (name(10), city, age); |
索引 (name, city, age) 等價於擁有:
(name, city, age)(name, city)(name)不會用到: (city, age)、(age)、(city) — 因為未包含最左列 name。
WHERE、JOIN ON、ORDER BY、GROUP BY 的欄位=, >, >=, <, <=, BETWEEN, IN, LIKE 'prefix%'LIKE '%suffix', LIKE '%mid%', NOT IN, <>, 函數運算 (如 YEAR(date))、隱含型別轉換INSERT/UPDATE/DELETE 需同步維護索引樹| 技巧 | 說明 | 正確範例 | 錯誤範例 |
|---|---|---|---|
| 短索引 | 字串只索引前綴長度 | INDEX idx_name (name(10)) | INDEX idx_name (name(255)) |
| 避免 NULL | 含 NULL 列不進索引,組合索引失效 | NOT NULL DEFAULT '' | 預設 NULL |
| 不在索引列運算 | 函數/運算導致索引失效 | WHERE create_time > '2023-01-01' | WHERE YEAR(create_time) > 2023 |
| 用 NOT EXISTS 代替 NOT IN | NOT IN 不走索引 | WHERE NOT EXISTS (SELECT 1 FROM b WHERE b.id=a.id) | WHERE id NOT IN (SELECT id FROM b) |
<> 改寫 | 不走索引 | WHERE id > 3 OR id < 3 | WHERE id <> 3 |
| ORDER BY 用索引順序 | 避免 filesort | 索引 (a,b) → ORDER BY a,b | ORDER BY b,a |
EXPLAIN SELECT * FROM t WHERE name='admin' AND city='Taipei';
關鍵欄位:
- type: ref/range/ALL (ref 最理想)
- possible_keys: 可能用到的索引
- key: 實際使用的索引
- key_len: 使用的索引長度
- rows: 預估掃描行數
- Extra: Using index / Using where / Using filesort 等建議
索引只是優化因素之一,大數據量還需配合 SQL 改寫、分區表、讀寫分離、快取等綜合手段。