索引是關聯式資料庫效能的核心。本文涵蓋索引建立/刪除/查看語法、索引類型(普通、唯一、全文、組合)、最左前綴原理、聚簇與非聚簇索引差異、以及 10 大優化避坑原則,助您從根本上解決慢查詢問題。
-- 1. ALTER TABLE(支援主鍵、唯一、普通)
ALTER TABLE tbl ADD INDEX idx_name (col1, col2);
ALTER TABLE tbl ADD UNIQUE uk_name (col);
ALTER TABLE tbl ADD PRIMARY KEY (col);
-- 2. CREATE INDEX(不支援主鍵)
CREATE INDEX idx_name ON tbl (col(length));
CREATE UNIQUE INDEX uk_name ON tbl (col);
-- 3. 建表時同步建立
CREATE TABLE tbl (
id INT PRIMARY KEY,
title VARCHAR(255),
INDEX idx_title (title(50)),
UNIQUE uk_email (email)
);
DROP INDEX idx_name ON tbl;
ALTER TABLE tbl DROP INDEX idx_name;
ALTER TABLE tbl DROP PRIMARY KEY; -- 僅刪主鍵
SHOW INDEX FROM tbl;
SHOW KEYS FROM tbl;
重點欄位:Cardinality(基數,唯一值估計)、Non_unique、Index_type(BTREE/FULLTEXT/HASH/RTREE)。
| 類型 | 關鍵字 | 特性 | 適用場景 |
|---|---|---|---|
| 普通索引 | INDEX | 無限制,允許 NULL、重複 | 一般查詢加速 |
| 唯一索引 | UNIQUE | 值唯一,允許多個 NULL | 業務鍵(Email、手機號) |
| 主鍵索引 | PRIMARY KEY | 唯一、非 NULL、聚簇索引 | 表主鍵 |
| 全文索引 | FULLTEXT | MyISAM/InnoDB 5.6+,中文需分詞器 | 長文本搜尋 |
| 組合索引 | INDEX (a,b,c) | 最左前綴原理 | 多條件查詢 |
建立 INDEX idx_a_b_c (a, b, c) 實際等同於擁有:
(a, b, c)(a, b)(a)可用到索引的查詢:
WHERE a = 1
WHERE a = 1 AND b = 2
WHERE a = 1 AND b = 2 AND c = 3
WHERE a = 1 ORDER BY b
用不到索引的查詢:
WHERE b = 2 -- 缺少最左列 a
WHERE c = 3 -- 缺少最左列 a
WHERE a = 1 AND c = 3 -- 中間斷層,只用到 (a)
| 特性 | 聚簇索引 | 非聚簇索引 |
|---|---|---|
| 資料儲存 | 葉節點直接存完整行資料 | 葉節點存主鍵值,需回表 |
| 每表數量 | 唯一一個(主鍵) | 可多個 |
| 範圍查詢 | 極快(順序讀取) | 需回表,較慢 |
| 插入效能 | 主鍵有序最佳 | 需維護多棵 B+ 樹 |
最佳實踐:InnoDB 必須有主鍵,建議用 BIGINT AUTO_INCREMENT 單調遞增,避免 UUID/字串主鍵導致頁分裂。
NOT NULL DEFAULT ''。VARCHAR(255) 前綴長度 10-20 即可區分,節省空間與 I/O。INDEX idx_title (title(20))WHERE YEAR(create_time) = 2023 ❌ → WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01' ✅LIKE 'abc%' ✅ 走索引;LIKE '%abc%' ❌ 全表掃描。INDEX (where_col, order_col)。Using index)避免回表。JOIN、WHERE、ORDER BY、GROUP BY 涉及欄位優先建索引。Cardinality 統計資訊,讓優化器做正確決策。| 場景 | 聚簇 | 非聚簇 |
|---|---|---|
| 頻繁範圍查詢 | ✅ | ❌ |
| 頻繁更新索引欄 | ❌ | ✅ |
| 主鍵/外鍵 | ✅ | ✅ |
| 極少數值(如性別) | ❌ | ❌(低選擇性) |
| 大量唯一值 | ❌ | ✅ |
索引優化是持續迭代的過程:觀察慢查詢 → EXPLAIN 分析 → 調整索引/語句 → 驗證效果。沒有萬能索引,只有適合當前業務查詢模式的索引。