怎么看 EXPLAIN
输出里的 type
字段
type表示 MySQL 如何查找表中行,它直接反映连接效率。从好到差大致是:
system≈
const>
eq_ref>
ref>
range>
index>
ALL。出现
ALL意味着全表扫描,基本等于没走索引;
index是走索引但要遍历整个索引树,也不理想。
const:主键或唯一索引等值查询,只匹配一行,最快
ref:非唯一索引等值查询(比如
WHERE status = 'active'),可能返回多行
range:范围查询(
BETWEEN、
>、
IN等),注意
IN里值太多会退化成
ALL如果
type是
ALL或
index,优先检查是否缺失索引,或索引列顺序是否匹配
WHERE条件
key
和 possible_keys
不一致说明什么
possible_keys是 MySQL 认为能用上的索引列表,
key是最终选中的那个。两者不一致很常见,但需警惕以下情况:
possible_keys有值,
key却是
NULL:说明优化器判断走索引比全表扫描还慢(比如表很小、或者索引选择性极差)
key选了低效索引:比如你建了
(a, b)联合索引,但查询只用了
b,MySQL 可能选错索引,这时加
FORCE INDEX验证效果 联合索引中,
WHERE条件跳过左列(如索引是
(user_id, created_at),但只查
created_at > '2024-01-01'),
key可能为空或降级为
index
Extra
里哪些值必须处理
Extra是执行过程的补充信息,其中几个值几乎等于性能红灯:
Using filesort:需要额外排序,没走索引排序。要么加覆盖索引(把
ORDER BY字段包含进索引),要么确认是否真需要排序
Using temporary:创建临时表,常见于
GROUP BY、
DISTINCT或复杂
JOIN。检查分组字段是否有索引,或能否改写避免临时表
Using index condition:正常,表示用了索引下推(ICP),是优化项,不是问题
Using where:说明存储引擎返回行后,Server 层还要再过滤——可能是索引没覆盖
WHERE全部条件,也可能是用了函数/表达式导致索引失效(如
WHERE YEAR(created_at) = 2024)
为什么加了索引 EXPLAIN
还不走
索引存在 ≠ 查询一定用。常见原因包括:
查询条件对字段用了函数或计算,比如WHERE UPPER(name) = 'JOHN'或
WHERE price + 10 > 100,会跳过索引 隐式类型转换,比如
user_id是
INT,但写成
WHERE user_id = '123'(字符串),MySQL 可能放弃索引 统计信息过期,执行
ANALYZE TABLE table_name更新后重看
EXPLAIN数据分布倾斜,比如某值占 95% 行数,优化器认为走索引更慢,可加
FORCE INDEX强制验证实际耗时
EXPLAIN SELECT * FROM orders WHERE status = 'shipped' AND created_at > '2024-01-01';
真正卡点往往不在单个字段有没有索引,而在于联合索引的列顺序、查询条件是否满足最左前缀,以及
WHERE/
ORDER BY/
SELECT三者字段能否被同一个索引覆盖。别只盯着
key是否非空,要通读
type、
key_len、
rows、
Extra四个字段组合起来看。
