索引是關係型數據庫性能的「加速器」。本文從底層算法(B+Tree vs Hash)、EXPLAIN 執行計劃解讀、核心列(type、key、rows、Extra)含義,到實戰索引設計原則,構建完整的索引優化知識體系。
=、IN),不支援範圍/排序,Memory 引擎預設。EXPLAIN SELECT `birthday` FROM `user` WHERE `birthday` < '1990/2/2';
| 列名 | 含義 | 關鍵判讀 |
|---|---|---|
id | 查詢序號 | 越大優先執行;相同則按順序 |
select_type | 查詢類型 | SIMPLE、PRIMARY、SUBQUERY、DERIVED、UNION 等 |
table | 涉及表 | 關聯查詢時顯示別名或衍生表 |
type | 訪問類型(核心) | system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL,目標至少達 range,最佳 ref/const |
possible_keys | 可能用到的索引 | 為 NULL 則無可用索引,需檢查 WHERE/ON 條件列 |
key | 實際使用的索引 | 為 NULL 表示全表掃描;PRIMARY 表走主鍵 |
key_len | 索引長度 | 越短越好(不損失精度前提),推斷聯合索引用了幾列 |
ref | 與 key 配合的列/常量 | const 表示常量等值匹配 |
rows | 預估掃描行數 | InnoDB 為估算值,越小越好 |
Extra | 額外信息 | Using index(覆蓋索引)、Using where、Using temporary、Using filesort(需優化) |
id: 1 select_type: SIMPLE table: user type: range possible_keys: birthday key: birthday key_len: 4 ref: const rows: 1 Extra: Using where; Using index
解讀:走 birthday 索引範圍掃描,覆蓋索引,預估 1 行,性能極佳。
SIMPLE:無子查詢、UNION 的簡單查詢。PRIMARY:包含子查詢的最外層查詢。SUBQUERY:SELECT 子句中的子查詢。DERIVED:FROM 子句衍生出的臨時表(子查詢)。UNION:UNION 中第二或之後的 SELECT。UNION RESULT:UNION 產生的結果集。| 值 | 性質 | 建議動作 |
|---|---|---|
| Using index | 🟢 好 | 覆蓋索引,無需回表 |
| Using where | 🟡 中性 | Server 層過濾,結合索引通常無問題 |
| Using temporary | 🔴 差 | 產生臨時表(GROUP BY/DISTINCT/ORDER BY 不同),優化索引或拆分查詢 |
| Using filesort | 🔴 差 | 文件排序(無索引支援 ORDER BY),加索引或調整 SQL |
| Impossible WHERE | 🟢 好 | WHERE 條件永假,優化器直接返回空集 |
(a,b,c),查詢必須從最左列開始匹配(a、a,b、a,b,c),中間斷點後列失效。COUNT(DISTINCT col)/COUNT(*) > 0.1 為宜)。SELECT a,b FROM t WHERE c=1 建 (c,a,b),避免回表。WHERE YEAR(date)=2024 → WHERE date >= '2024-01-01')LIKE '%abc%' 前導通配符OR 條件兩側索引不一致ANALYZE TABLE 更新統計信息。BIGINT AUTO_INCREMENT PK。EXPLAIN 是索引優化的「聽診器」,重點關注 type、key、rows、Extra 四大核心指標。遵循「最左前綴、高區分度、覆蓋索引、避免失效」四大原則,配合 pt-query-digest 定期掃描慢查詢,持續迭代索引策略,是 MySQL 高性能的不二法門。