在關係型數據庫中,索引是提升查詢速度的最關鍵結構。MySQL 所有索引均以 B+ 樹 形式存儲。若無索引,執行查詢時 MySQL 必須掃描整張表(全表掃描),數據量越大代價越高;有了索引,MySQL 可直接定位到目標行,對於百萬級數據,速度提升可達百倍以上。
| 類型 | 特點 | 創建語法示例 | 適用場景 |
|---|---|---|---|
| 普通索引 | 最基本,無唯一性約束 | CREATE INDEX idx_name ON tbl(col);ALTER TABLE tbl ADD INDEX idx_name (col); |
頻繁出現在 WHERE、JOIN、ORDER BY 中的非唯一列 |
| 唯一索引 | 索引列值不可重複,允許 NULL | CREATE UNIQUE INDEX uk_email ON users(email); |
業務鍵(如郵箱、身份證號) |
| 主鍵 | 特殊唯一索引,不允許 NULL,每表僅一個 | CREATE TABLE t (id INT PRIMARY KEY, ...);ALTER TABLE t ADD PRIMARY KEY (id); |
表的唯一標識,通常為自增 ID |
| 全文索引 | MySQL 3.23.23+ 支持,針對 VARCHAR/TEXT | ALTER TABLE articles ADD FULLTEXT(content); |
大文本字段的關鍵詞搜索(中文需分詞器) |
| 空間索引 | MySQL 4.1+ 支持,針對幾何類型 | ALTER TABLE geom ADD SPATIAL INDEX(loc); |
GIS 應用,經緯度範圍查詢 |
假設表 people 有索引 INDEX idx_name_age (lastname, firstname, age):
WHERE lastname='Smith'、WHERE lastname='Smith' AND firstname='John'、WHERE lastname='Smith' AND firstname='John' AND age>30WHERE firstname='John'(非最左列)、WHERE age>30(跳過前綴)經驗法則:將選擇性最高(唯一值最多)的列放在最左;避免過多列組合(建議 ≤3 列),否則索引膨脹、維護成本高。
EXPLAIN SELECT ... 觀察 type(應為 ref/range/eq_ref,避免 ALL)、key(實際用到的索引)、rows(預估掃描行數)。Extra 顯示 Using index,避免回表,極大提速。WHERE YEAR(create_time)=2023 → 改為 WHERE create_time >= '2023-01-01' AND create_time < '2024-01-01'WHERE phone=13800138000(phone 為 VARCHAR) → 加引號LIKE '%keyword%' 導掃描 → 僅 LIKE 'keyword%' 走索引OR 連接非索引列 → 改用 UNION 或建立聯合索引ANALYZE TABLE 更新統計信息;OPTIMIZE TABLE 整理碎片(InnoDB 可用 ALTER TABLE ... ENGINE=InnoDB 重建)。-- 原始慢查詢(三張表無有效索引)
SELECT t1.id, t2.name, t3.amount
FROM orders t1
JOIN customers t2 ON t1.cust_id = t2.id
JOIN payments t3 ON t1.id = t3.order_id
WHERE t1.status = 'paid' AND t2.city = 'Beijing';
-- 優化步驟
ALTER TABLE orders ADD INDEX idx_status_cust (status, cust_id);
ALTER TABLE customers ADD INDEX idx_city_id (city, id);
ALTER TABLE payments ADD INDEX idx_order_id (order_id);
-- EXPLAIN 驗證:type 變為 ref,rows 大幅下降
索引是雙刃劍:讀快寫慢、佔用空間。核心原則是「為查詢建索引,而非為表建索引」。持續監控慢查詢日誌(slow_query_log)、定期 EXPLAIN、遵循最左前綴、善用覆蓋索引,是將 MySQL 性能榨乾的必經之路。