索引是資料庫效能的核心杠桿。本文系統整理索引建立語法、類型選擇、ALTER TABLE 管理操作、SHOW INDEX 解讀與避坑原則,助您構建高效的索引策略。
| 類型 | 關鍵字 | 特性 | 適用場景 |
|---|---|---|---|
| 主鍵 | PRIMARY KEY | 唯一、非空、聚簇索引(InnoDB) | 每張表必須、業務主鍵 |
| 唯一索引 | UNIQUE | 值唯一、允許多個 NULL | 業務唯一鍵(Email、手機、身分證) |
| 普通索引 | INDEX / KEY | 允許重複、允許 NULL | 查詢/連接/排序/分組欄位 |
| 全文索引 | FULLTEXT | 支援自然語言/布林模式搜尋 | 文章、日誌、商品描述等長文本 |
| 空間索引 | SPATIAL | GIS 幾何類型 | 地理位置、幾何運算 |
| 複合索引 | (col1, col2, ...) | 最左前綴原則、覆蓋索引潛力 | 多欄位組合查詢、排序、分組 |
-- 1. 建表時指定
CREATE TABLE t (
id INT PRIMARY KEY,
email VARCHAR(100) UNIQUE,
name VARCHAR(50),
INDEX idx_name (name),
FULLTEXT ft_content (content)
);
-- 2. ALTER TABLE 新增
ALTER TABLE t ADD UNIQUE INDEX uk_phone (phone);
ALTER TABLE t ADD INDEX idx_created (created_at);
-- 3. CREATE INDEX(不支援主鍵)
CREATE UNIQUE INDEX uk_email ON t (email);
CREATE INDEX idx_name ON t (name DESC); -- 降序索引(8.0+ 生效)
-- 查看索引 SHOW INDEX FROM t \G -- 關鍵欄位:Key_name, Seq_in_index, Column_name, Cardinality, Sub_part, Index_type, Comment -- 刪除索引 ALTER TABLE t DROP INDEX uk_phone; -- 或 DROP INDEX uk_phone ON t; -- 修改主鍵(需先刪除舊主鍵) ALTER TABLE t DROP PRIMARY KEY, ADD PRIMARY KEY (new_id);
索引 (a, b, c) 可支援:
WHERE a = ?WHERE a = ? AND b = ?WHERE a = ? AND b = ? AND c = ?ORDER BY a, b, c / GROUP BY a, b, c不可支援: WHERE b = ?、WHERE a = ? AND c = ?(跳過 b)、WHERE a > ? AND b = ?(範圍查詢中斷前綴)。
若 SELECT a, b FROM t WHERE c = ?,且存在索引 (c, a, b),則查詢僅掃描索引樹,不回主鍵聚簇索引取行,效能提升數倍。EXPLAIN 中 Extra: Using index 表示命中覆蓋索引。
WHERE varchar_col = 123(需 '123')WHERE DATE(created_at) = '2024-01-01' → 改 WHERE created_at >= '2024-01-01' AND created_at < '2024-01-02'LIKE '%keyword%' 以萬用字元開頭OR 連接條件且未全覆蓋索引:WHERE a=1 OR b=2 → 改 UNION ALLANALYZE TABLE t 更新 Cardinalitypt-index-usage 分析慢查詢日誌,找出未使用索引並 DROP。OPTIMIZE TABLE t 或 ALTER TABLE t ENGINE=InnoDB 重建索引,回收空間、修復統計資訊。Handler_read_rnd_next(全表掃描)、Innodb_buffer_pool_reads(磁碟讀取)、Created_tmp_disk_tables(臨時表落盤)。pk_ 主鍵、uk_ 唯一、idx_ 普通、ft_ 全文、sp_ 空間,便於自動化腳本識別。索引是「寫入換讀取」的交易。每新增一個索引,INSERT/UPDATE/DELETE 都要付出維護成本。請基於慢查詢日誌實證建立索引,而非憑直覺,並定期清理無效索引,保持精簡高效。