MySQL 8.4 查询慢时,可先用 EXPLAIN FORMAT=TRADITIONAL 查看访问方式、实际选择的索引与估算扫描行数,再结合原始 SQL、参数和表结构判断。possible_keys 是候选索引,key 才是所选索引,估算计划本身不能证明实际耗时。

适用版本与准备

本文依据发布时查阅的 MySQL 8.4 官方手册整理,适用于 MySQL 8.4,未在目标数据库实测。请使用已授权的诊断连接,先确认实例、数据库与版本。示例中的 orders、id、customer_id、created_at 均为占位对象,需要替换为真实表和字段。账号应具备被解释语句所需权限,涉及视图还可能需要 SHOW VIEW 权限,见 EXPLAIN 官方语法与权限说明。

SELECT VERSION(), DATABASE();
SHOW CREATE TABLE orders;
SHOW INDEX FROM orders;

保存表结构、现有索引和待排查 SQL。使用与故障请求相同类型和有代表性的参数,记录查询条件与返回规模,分享资料前去除业务敏感值。SHOW INDEX 用来核对索引列及顺序,不能凭索引名称推断其定义。

第一步,获取固定格式的估算计划

EXPLAIN FORMAT=TRADITIONAL
SELECT id, created_at
FROM orders
WHERE customer_id = 123
ORDER BY created_at DESC
LIMIT 20;

FORMAT=TRADITIONAL 明确选择表格格式,避免会话默认输出格式影响阅读。EXPLAIN 用来了解优化器拟定的执行方案,排查时应保存完整结果,不能只截取 key 一列。官方介绍见 使用 EXPLAIN 优化查询。

第二步,按同一行结合阅读关键列

  • table 用于确认当前计划行对应哪个表或派生结果。
  • type 表示访问方式。ALL 表示全表扫描,但是否需要优化仍取决于表规模和条件选择性。
  • possible_keys 列出候选索引,key 表示实际选择的索引。候选存在不保证最终使用。
  • rows 是预计检查的行数,filtered 是预计经表条件过滤后保留的百分比。对 InnoDB,这些值属于估算。
  • Extra 补充排序、过滤等执行信息,应结合整体计划解读。

各列定义见 EXPLAIN 输出官方说明。例如 rows 与返回结果数量相差很大时,可作为继续核对过滤条件和访问路径的线索,不能把二者直接等同。多表连接还需结合连接顺序观察各表的工作量。

第三步,形成可验证的改动假设

把 WHERE、连接条件和 ORDER BY 与索引定义并排核对,明确希望减少哪一步的扫描或排序。对于示例查询,可将 customer_id 与 created_at 的索引组织作为评估方向,但是否适合创建索引,需要结合已有索引、数据分布和写入负担确定。本文未提供通用建索引命令。

  1. 先保存原始计划、查询参数、数据规模与实际业务耗时。
  2. 在可控测试环境中一次只调整一个因素,保留结果一致性的验证。
  3. 重新获取相同 SQL 和参数的计划,并在可比负载下测量实际查询。
  4. 确认收益与写入代价后,再按变更流程安排生产操作。

EXPLAIN 可帮助评估索引及连接顺序,也可用于修改前后的比较,见 官方优化流程说明。计划发生变化本身不能替代业务验证。

常见问题与边界

可以直接把 EXPLAIN 换成 EXPLAIN ANALYZE 吗?

EXPLAIN ANALYZE 会真正运行语句,并报告实际时间、行数和循环次数。在 MySQL 8.4 中它使用 TREE 格式。只有在确认执行成本、数据访问和环境允许后,才对受控查询使用,不应直接给未知慢 SQL 加上 ANALYZE 后在繁忙实例执行。详细行为见 EXPLAIN ANALYZE 官方说明。

key 有值,为什么请求仍然慢?

索引被使用只说明访问路径的一部分。应继续核对扫描规模、连接、排序以及实际等待。若 SQL 卡住并出现事务阻塞,可参考本站 MySQL 8.4 锁等待与阻塞连接排查。本文仅为资料整理,没有提供亲测结果或性能提升数值。