mysql数据库中查询语句的EXPLAIN执行分析

来源:这里教程网 时间:2026-02-28 20:39:52 作者:

EXPLAIN 输出中 type 字段为 ALL 就一定慢吗

不一定。type =

ALL
表示全表扫描,但实际性能取决于数据量、索引选择性、缓存命中率和查询条件是否能利用 WHERE 推进过滤。例如:一张只有 100 行的配置表,
ALL
扫描比走索引还快;而对千万级订单表执行
SELECT * FROM orders WHERE status = 'pending'
却没给
status
建索引,这时
ALL
就是瓶颈。

判断依据优先看

rows
列估算扫描行数,再结合
key
是否为
NULL
(未用索引)和
Extra
中是否有
Using where
Using index
。如果
rows
远大于实际返回结果数,且
key
NULL
,才真正值得优化。

为什么 EXPLAIN 显示用了索引,但查询还是慢

常见原因包括:

key
列显示用了索引,但
possible_keys
key
不一致,说明 MySQL 选错了索引——可通过
FORCE INDEX
强制或
ANALYZE TABLE
更新统计信息
索引覆盖不足,导致回表次数多:
Extra
出现
Using where; Using index
是好信号,但若只有
Using index condition
,说明用了 ICP(索引条件下推),仍需回主键查找其他字段
索引字段存在隐式类型转换,比如
WHERE user_id = '123'
user_id
INT
,MySQL 会放弃索引做全扫描
查询涉及
ORDER BY
GROUP BY
,但排序字段不在联合索引最左前缀上,导致无法利用索引排序,出现
Using filesort

EXPLAIN FORMAT=JSON 比传统格式多什么关键信息

FORMAT=JSON
提供更底层的执行决策依据,尤其适合排查优化器误判。它明确给出:

used_columns
:实际参与查询的列,帮你确认是否写了多余字段
condition_filtering_pct
:WHERE 条件的过滤效率预估,低于 10% 往往提示索引无效或条件太宽泛
attached_condition
:下推到存储引擎层的过滤条件,可对比
attached_subqueries
看子查询是否被提前执行
using_index
using_index_condition
的布尔值比传统格式的
Extra
更精确,避免歧义

执行方式:

EXPLAIN FORMAT=JSON SELECT * FROM users WHERE age > 30 AND city = 'Beijing';

如何用 EXPLAIN 快速定位 JOIN 性能问题

重点观察驱动表(第一行)的

rows
和被驱动表(后续行)的
type
key

驱动表
rows
过大(如 10 万+),说明外层结果集膨胀,应优先缩小驱动表范围(加 LIMIT / 更严格 WHERE)
被驱动表
type
ALL
index
,且
key
NULL
,说明 ON 条件字段没索引或索引失效
Extra
出现
Using join buffer (Block Nested Loop)
,代表 MySQL 在内存中缓存了驱动表部分数据做嵌套循环,此时应检查
join_buffer_size
是否合理,或考虑改写为 EXISTS / 子查询
多表 JOIN 时,
table
列顺序不等于 SQL 中书写顺序,MySQL 可能重排执行顺序——用
STRAIGHT_JOIN
强制顺序可验证是否重排导致变慢

复杂 JOIN 建议先用

EXPLAIN
看执行计划,再逐表检查关联字段是否有合适索引,而不是一上来就加复合索引。

索引不是越多越好,

EXPLAIN
key_len
偏小、
rows
偏大、
Extra
频繁出现
Using temporary
Using filesort
这些信号,往往比“有没有索引”更能说明问题。

相关推荐