判断是否走索引需看EXPLAIN的key和type:key非NULL且type为ref/range/const/eq_ref表示有效使用索引;type=ALL为全表扫描,常见于函数操作、隐式转换、联合索引顺序不匹配或OR分支未全覆盖索引。

怎么看 EXPLAIN 输出里有没有走索引
直接看 EXPLAIN 结果中的 type 和 key 两列最关键:key 非 NULL 表示用了索引;type 是 ref、range、const 或 eq_ref 通常说明走了有效索引;如果是 ALL,基本就是全表扫描。
常见误判点:
-
key显示某个索引名,但rows很大(比如接近表总行数),可能是索引选择性差或用了索引最左前缀不匹配 -
type是index(全索引扫描)≠ 走了高效索引,它只是遍历索引树而非数据行,仍可能很慢 - 有
Using filesort或Using temporary提示,说明排序/分组没利用索引完成,即使key不为空,性能也可能崩
为什么加了索引却显示 type=ALL
索引存在 ≠ 查询能用上。常见原因包括:
- WHERE 条件对字段做了函数操作,如
WHERE YEAR(create_time) = 2023—— 索引失效,改用create_time BETWEEN '2023-01-01' AND '2023-12-31' - 隐式类型转换,比如
user_id是INT,但写成WHERE user_id = '123',MySQL 可能放弃索引 - 联合索引顺序不匹配,例如索引是
(a, b, c),但查询只用了b = ?或c = ?,无法命中 - OR 条件中部分分支没索引,整个 WHERE 可能退化为全表扫描(除非所有 OR 分支都覆盖索引)
EXPLAIN FORMAT=TREE 和 FORMAT=TRADITIONAL 的区别
MySQL 8.0+ 支持 FORMAT=TREE,输出更贴近真实执行流程,尤其对复杂嵌套查询更直观:
-
FORMAT=TRADITIONAL是经典表格形式,适合快速扫关键字段(key/rows/Extra) -
FORMAT=TREE会展示“访问方法”“条件过滤率”“是否使用物化”等,比如看到-> Filter: (t.status = 'active')在索引扫描之后,说明过滤发生在引擎层而非存储层,效率较低 - 注意:有些旧客户端(如某些版本的 Navicat)不识别
FORMAT=TREE,会报错或忽略,建议优先用命令行或 MySQL Shell 执行
实际调优时容易被忽略的细节
很多同学看了 EXPLAIN 就以为完事了,但真正影响性能的常藏在细节里:
-
rows是估算值,不一定准;如果EXPLAIN显示 100 行,但实际执行慢,用SHOW PROFILE或performance_schema查看真实 I/O 和 CPU 时间 - 覆盖索引(
Extra: Using index)比非覆盖索引快得多,尽量让 SELECT 字段都在索引里,避免回表 - 对
ORDER BY字段建索引时,注意 ASC/DESC 匹配(MySQL 8.0+ 支持混合方向,但 5.7 及以前要求全部一致) - 统计信息过期会导致执行计划错误,定期运行
ANALYZE TABLE tbl_name更新行数和分布估算
执行计划不是一次性的快照,而是受数据分布、参数设置、甚至上次查询缓存状态影响的动态结果。别只信 EXPLAIN,要结合 slow_query_log 和真实执行时间交叉验证。










