mysql使用EXPLAIN分析查询执行计划

2次阅读

explain 显示查询执行计划而非结果,关键字段含 id、type(all 表示全表扫描需排查)、key(NULL 说明未用索引)、rows(预估扫描行数,越大越差)、extra(using filesort/temporary 意味着性能隐患);加索引未生效常因函数操作等导致优化器弃用索引。

mysql使用EXPLAIN分析查询执行计划

EXPLAIN 输出字段怎么看

mysqlEXPLAIN 不是告诉你“查到了什么”,而是告诉你“打算怎么查”。关键字段包括 idtypekeyrowsExtra。其中 type 值从好到差通常是:systemconst > eq_ref > ref > range > index > ALL;出现 ALL 意味着全表扫描,要优先排查。

key 显示实际用到的索引名,为 NULL 说明没走索引;rows 是 MySQL 预估需要扫描的行数(不是结果行数),值越大越危险;Extra 里出现 Using filesortUsing temporary 通常意味着排序或分组没走索引,性能开销大。

为什么加了索引还是没走

常见原因不是索引没建,而是查询写法或数据分布导致优化器放弃使用。比如:

  • WHERE 条件对字段用了函数,如 WHERE YEAR(create_time) = 2023 → 改成 WHERE create_time >= '2023-01-01' AND create_time
  • 隐式类型转换,如 user_idint,但写成 WHERE user_id = '123'字符串字面量触发转换,可能使索引失效
  • 索引列在 OR 左右两侧,且只有一侧有索引 → 尝试改用 union 或确保两边都有对应索引
  • 统计信息过期,执行 ANALYZE table table_name 更新即可

如何看 JOIN 的执行顺序和效率

EXPLAINid 列决定执行顺序:相同 id 表示同一级操作,并按出现顺序执行;不同 id 中数字越小越先执行。对于 JOIN,MySQL 一般从小结果集驱动大表(即“驱动表”在 EXPLAIN 中排第一),但若驱动表没有合适索引,就会变成嵌套循环全扫。

检查点:

  • 确认被驱动表的 ON 条件字段是否走了索引(看 keytype
  • 避免 select *,尤其在多表 JOIN 时,字段越多,临时表/缓冲区压力越大
  • 如果 Extra 出现 Using join buffer (Block Nested Loop),说明没走索引,正退化为慢速连接方式
EXPLAIN SELECT u.name, o.amount  FROM users u  JOIN orders o ON u.id = o.user_id  WHERE u.status = 'active';

EXPLAIN format=json 能看到什么额外信息

默认的表格输出太简略。EXPLAIN FORMAT=JSON 会返回结构化 JSON,包含更细粒度的决策依据,比如:

  • used_columns:该表实际参与查询的列(帮你发现冗余字段)
  • condition_filtering_pct:条件过滤率预估,低于 10% 可能说明选择性差
  • attached_condition:下推到存储引擎层的 WHERE 条件,有助于判断索引是否被充分利用
  • query_cost:优化器估算的总成本,可用于横向对比两种写法的代价

注意:FORMAT=JSON 不支持所有 MySQL 版本(5.6+ 开始支持,但 5.7 才较稳定),且无法直接用于生产慢查监控——它本身不记录执行时间,只是计划预估。

最常被忽略的一点:EXPLAIN 不执行语句,也不反映锁行为、MVCC 版本链长度、buffer pool 命中率等运行时状态。真正卡顿的查询,光看 EXPLAIN 往往不够。

text=ZqhQzanResources