MySQL EXPLAIN ANALYZE 面试总答偏?4个字段把估算和实测对上,别再只看 key

MySQL EXPLAIN ANALYZE 面试总答偏?4个字段把估算和实测对上,别再只看 key

聚焦 MySQL 面试里的执行计划追问,用 key、key_len、rows、filtered 4 个字段串起 EXPLAIN 与 EXPLAIN ANALYZE,给出可复述的排查顺序和避坑清单。

如果你在 MySQL 面试里只说「看 key 有没有值」,很容易被继续追问:用了联合索引的哪一段?rows 是真实扫描行数吗?Using filesort 就一定要加索引吗?
更稳的做法,是拿同一条 SQL 连续跑 EXPLAINEXPLAIN ANALYZE,用 keykey_lenrowsfiltered 4 个字段先读懂优化器的估算,再用实际执行结果校验。这样回答不会停在口诀,而是能落到「计划是什么、估算准不准、下一步查哪里」。
本文示例按 MySQL 8.4 参考手册的字段语义说明;不同版本的输出格式可能有差异,现场先确认题目中的版本。1

先记住:两个命令不是一回事

普通 EXPLAIN 不会执行查询,它展示优化器准备采用的执行计划。EXPLAIN ANALYZE 会实际执行语句,并把估算的行数、时间与真实返回行数、循环次数放在执行树里,适合检查估算和实测是否偏离。2
面试现场可以先说这句:
我先用 EXPLAIN 看访问路径和估算,再用只读的 EXPLAIN ANALYZE 验证估算是否接近真实执行;因为后者会执行查询,生产环境不能直接对任意语句使用。
这句话把工具边界排查顺序一起交代了。

用一条 SQL 练完这套读法

假设订单表上有联合索引:
KEY idx_user_status_time (user_id, status, created_at)
待排查的查询是:
SELECT id, status, created_at
FROM orders
WHERE user_id = 42
  AND status = 'PAID'
  AND created_at >= '2026-01-01'
ORDER BY created_at DESC
LIMIT 20;
先看计划:
EXPLAIN
SELECT id, status, created_at
FROM orders
WHERE user_id = 42
  AND status = 'PAID'
  AND created_at >= '2026-01-01'
ORDER BY created_at DESC
LIMIT 20;
确认是只读查询、数据量和执行时机都可接受后,再做实测:
EXPLAIN ANALYZE
SELECT id, status, created_at
FROM orders
WHERE user_id = 42
  AND status = 'PAID'
  AND created_at >= '2026-01-01'
ORDER BY created_at DESC
LIMIT 20;
不要把两条命令当成「一个看索引、一个看速度」这么粗略。面试官真正想听的是:你能不能把索引选择、索引使用深度、行数估算和过滤效果串起来。

4 个字段,按这个顺序读

1. key:实际用了哪一个索引

possible_keys 只表示优化器认为可能有用的索引;key 才是这次计划实际选中的索引。两者不能混为一谈。1
对上面的查询,第一问是:
  • key 是否为 idx_user_status_time
  • 如果 keyNULL,是否缺少合适索引,或者优化器判断走索引不划算?
  • possible_keys 有值但 key 不同,实际选中的路径是什么?
不要只看到 possible_keys=idx_user_status_time 就回答「已经走联合索引」。正确表述是:
possible_keys 是候选集合,key 才是实际选中的索引。我先确认真正的访问路径,再解释为什么选它。

2. key_len:联合索引实际用了多深

key_len 是所选键的长度,可以帮助判断复合索引实际使用了多少部分;它不是简单的「用了几列」,因为列的数据类型和是否允许 NULL 都会影响键长度。1
假设索引定义为:
(user_id, status, created_at)
你不能只凭 key_len 的一个数字,脱离表结构直接说「用了前两列」。更稳的现场步骤是:
  1. 先看 SHOW CREATE TABLE orders,确认 3 列的数据类型、字符集和 NULL 属性。
  2. 再拿 key_len 与每一列的索引长度相加结果对照。
  3. 最后结合 WHERE 条件判断,是等值条件连续命中,还是在某个范围条件处停止了深入匹配。
MySQL 官方把联合索引看成按列顺序排列的组合值。索引 (col1, col2, col3) 可以支持 (col1)(col1, col2) 和完整三列这样的左侧连续前缀;只查 (col2)(col2, col3),不能作为索引查找的左侧前缀。3
所以面试中不要背成「联合索引只能从第一列开始」。更准确的说法是:
能否用于定位,取决于查询条件是否形成索引定义的左侧连续前缀;key_len 用来辅助确认实际深入了多少。

3. rows:优化器预计要检查多少行

rows 是优化器估算的、执行查询时需要检查的行数。对 InnoDB 来说它是估计值,不是真实计数。1
因此,看到 rows=100000 时不要直接说「这条 SQL 扫了一万行」;应该说:
计划阶段预计需要检查约 100000 行,真实执行量要用 EXPLAIN ANALYZE 对照。
如果 rows 明显偏大,排查方向包括:
  • 条件没有形成有效的索引查找前缀;
  • 统计信息不能代表当前数据分布;
  • 条件选择性低,索引排除了很少的行;
  • 查询本身确实需要读取较大的候选范围。
这里先不要急着「加一个索引」。先确认 keykey_len,否则你可能只是在一个没有真正使用的索引上继续堆列。

4. filtered:剩下多少比例能通过表条件

filtered 是表条件过滤后的估算百分比。比如 rows=1000filtered=10.00,可以粗略理解为约有 1000 × 10% = 100 行进入后续连接;单表查询则可以把它当作判断残余过滤量的线索。1
它回答的是「读到候选行后,还剩多少」,不是「索引扫描了多少」。因此要和前面两个字段连起来看:
  • key 正确、key_len 只用了前一部分,rows 很大、filtered 很低:可能先定位出一大片候选,再靠表条件过滤;
  • key 正确、key_len 使用充分,rows 较小:计划阶段的候选范围更收敛;
  • rows 估算很小,但 EXPLAIN ANALYZE 的实际行数很大:优化器估算可能失真,应该检查数据分布和统计信息,而不是直接把估算当事实。

最后再看 typeExtra

虽然本文的核心是 4 个字段,但现场不能漏掉访问类型和附加信息。
type 表示访问方式。consteq_refrefrangeindexALL 代表不同层次的访问路径;ALL 通常意味着全表扫描,但不能只凭一个 type 就断定查询一定有问题。1
Extra 里如果出现 Using filesortUsing temporary,说明查询需要额外的排序或临时表处理。它们是需要解释的信号,不是「看到就必然加索引」的自动修复按钮。1
回答时可以按下面顺序走:
  1. 访问路径type 是否符合数据量和查询场景?key 实际选了什么?
  2. 索引深度key_len 说明联合索引用了多少,是否在范围条件处停止?
  3. 估算代价rows 预计要检查多少,filtered 预计还剩多少?
  4. 额外动作Extra 是否出现排序、临时表或其他需要验证的处理?
  5. 实测校验:用 EXPLAIN ANALYZE 看估算与真实行数、时间、循环次数是否一致。
MySQL 官方也建议检查查询是否真正使用了创建的索引,并用 EXPLAIN 验证,而不是只看建表语句或索引名称。4

面试官继续追问时,照这个模板答

我会先看 typekey,确认访问方式以及实际使用的索引;再看 key_len,结合表结构判断联合索引用了哪些前缀。然后看 rowsfiltered,区分优化器预计检查多少候选行、过滤后还剩多少。最后看 Extra 是否有额外排序或临时表。普通 EXPLAIN 只是估算计划,我会在安全的只读环境用 EXPLAIN ANALYZE 做实测,比较估算行数和实际行数,再决定是检查统计信息、调整索引顺序,还是改写查询。
这段话里有三个边界要守住:
  • 不把候选索引说成已使用索引
  • 不把估算行数说成真实扫描行数
  • 不把一个提示字段直接等同于修复方案

4 个容易扣分的回答

看到 key 有值,就说「索引没问题」

索引被选中,不代表索引使用深度、行数估算和排序代价都理想。至少继续看 key_lenrowsfilteredExtra

看到 key_len 变大,就说「一定更快」

更长的索引使用范围可能减少候选行,但最终仍要看数据分布、实际行数和查询目标。key_len 是解释计划的证据,不是性能承诺。

rows 当成监控里的真实扫描量

它是计划阶段估算值。估算和实测差距很大时,问题可能在统计信息或数据分布,也可能在查询条件本身。

Using filesort 当成唯一结论

它表示额外排序步骤。是否值得改写查询或调整索引,要结合排序数据量、返回行数、业务延迟目标和 EXPLAIN ANALYZE 的实测结果。

练习清单:5 分钟完成一次复盘

拿一条你自己的慢查询,不要先改 SQL,按顺序记录:
  • typekeykey_lenrowsfilteredExtra 当前是什么;
  • 你认为它会检查多少候选行,过滤后会剩多少;
  • 在安全的只读环境运行 EXPLAIN ANALYZE 后,实际行数和时间是多少;
  • 估算与实测差异最大的地方是什么;
  • 你准备调整的是统计信息、索引顺序、查询写法,还是先不改;
  • 改动前后,是否用同一条 SQL、同一组参数和相近数据量复测。
练习的验收标准不是背出一串「索引优化口诀」,而是能在 60 秒内把一条 SQL 讲成一条证据链:实际走了什么、用了多深、估算多少、实测多少、下一步验证什么
求职面试实战指南

求职面试实战指南

求职面试全方向深度攻略,参考面灵AI博客选题风格,覆盖面试技巧、技术考点、简历优化与AI工具评测。

This story was produced automatically by a channel. One sentence is all it takes for Neodrop to keep producing for you.

Related content

  • Sign in to comment.