索引是資料庫效能優化的核心機制,合理設計索引可將查詢速度提升數十至數百倍。本文從索引基礎概念、類型分類、單列與組合索引對比、最左前綴原理、使用場景、失效條件、維護成本七個維度,系統講解 MySQL 索引實戰精要。
假設表 testIndex 有 1000 行資料,查詢 WHERE vc_Name='erquan':
| 類型 | 關鍵字 | 特點 | 適用場景 |
|---|---|---|---|
| 主鍵索引 | PRIMARY KEY | 唯一、非空、聚簇索引(InnoDB) | 每張表必須、業務主鍵 |
| 唯一索引 | UNIQUE | 值唯一、允許 NULL | 業務唯一約束(郵箱、身分證) |
| 普通索引 | INDEX / KEY | 無約束、可重複、可 NULL | 高頻查詢條件、JOIN 關聯欄位 |
| 全文索引 | FULLTEXT | 支援自然語言/布爾模式搜尋 | 長文本搜尋(MySQL 5.6+ InnoDB 支援) |
| 組合索引 | INDEX(a,b,c) | 多列組合、遵循最左前綴 | 多條件組合查詢、排序優化 |
| 空間索引 | SPATIAL | GIS 幾何類型 | 地理位置、幾何運算 |
-- 1. 建表時指定
CREATE TABLE tb (
id INT PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100),
INDEX idx_name (name),
UNIQUE uk_email (email)
);
-- 2. ALTER TABLE 添加
ALTER TABLE tb ADD INDEX idx_name (name);
ALTER TABLE tb ADD UNIQUE uk_email (email);
-- 3. CREATE INDEX 獨立創建
CREATE INDEX idx_name ON tb(name);
CREATE UNIQUE INDEX uk_email ON tb(email);
-- 4. 組合索引(指定前綴長度優化)
CREATE INDEX idx_name_city ON tb(name(10), city); -- name 只索引前 10 字符
-- 5. 刪除索引
DROP INDEX idx_name ON tb;
ALTER TABLE tb DROP INDEX idx_name;
場景: 表 myIndex 10000 行,查詢:
SELECT i_testID FROM myIndex
WHERE vc_Name='erquan' AND vc_City='鄭州' AND i_Age=25;
idx_name)vc_Name='erquan' → 回表 → 過濾 city、ageidx_name_city_age (vc_Name, vc_City, i_Age)(name, city, age) 排序存儲組合索引(a,b,c)等價於擁有三個索引:(a)、(a,b)、(a,b,c)
但不包含:(b)、(c)、(b,c)、(a,c)
定義: 組合索引的 B+ 樹按索引定義列順序構建排序規則,查詢必須從最左列開始連續匹配才能利用索引。
| 查詢條件 | 索引 (a,b,c) | 是否用到索引 | 用到的索引列 |
|---|---|---|---|
| WHERE a=1 | ✓ | 是 | a |
| WHERE a=1 AND b=2 | ✓ | 是 | a,b |
| WHERE a=1 AND b=2 AND c=3 | ✓ | 是 | a,b,c |
| WHERE b=2 | ✗ | 否 | 全表掃描 |
| WHERE b=2 AND c=3 | ✗ | 否 | 全表掃描 |
| WHERE a=1 AND c=3 | △ | 部分 | 僅用 a(中間斷層) |
| WHERE a=1 ORDER BY b | ✓ | 是 | a,b(避免 filesort) |
| WHERE a=1 ORDER BY c | △ | 部分 | 用 a 過濾,但排序需 filesort |
=, >, >=, <, <=, BETWEEN, IN, LIKE 'prefix%'
LIKE '%abc'、LIKE '%abc%'WHERE YEAR(date_col)=2023、WHERE id+1=100、WHERE UPPER(name)='ABC'WHERE varchar_col = 123(數字比較字串)WHERE b=1、WHERE c=1、WHERE b=1 AND c=2WHERE idx_a=1 OR non_idx_b=2!=、NOT IN、NOT EXISTS(通常全表掃描)SHOW STATUS LIKE 'Handler_read%',Handler_read_key 高表示索引命中好-- 查看表索引
SHOW INDEX FROM tb;
-- 分析查詢執行計劃
EXPLAIN SELECT * FROM tb WHERE name='abc' AND city='北京';
-- 監控索引使用情況
SHOW STATUS LIKE 'Handler_read%';
-- Handler_read_key: 索引讀取次數(越高越好)
-- Handler_read_rnd_next: 全表掃描次數(越低越好)
-- 檢查未使用的索引 (MySQL 5.7+ sys schema)
SELECT * FROM sys.schema_unused_indexes;
索引設計是「讀寫平衡」的藝術。理解 B+ 樹結構、最左前綴原理、優化器決策邏輯,結合業務查詢模式,才能創建真正高效的索引體系。建議建立索引設計評審機制,上線前必經 EXPLAIN 驗證,上線後持續監控 sys.schema_unused_indexes 清理無效索引。