← 返回题目列表

MySQL Explain 主要看哪些字段?

高频 中等 第 14 / 28 题 更新于 2026/07/27
MySQLExplainSQL优化执行计划

简化版

Explain 主要看访问类型 type、使用的索引 key、扫描行数 rows、过滤比例 filtered 和额外信息 Extra。面试回答要强调:Explain 是优化器估算出的执行计划,不是 SQL 实际耗时本身,要结合真实数据量、索引和执行耗时一起判断。

详细版

常看的字段有:

  • id:查询块编号,复杂 SQL 中用于看执行层次。
  • select_type:普通查询、子查询、派生表等类型。
  • table:当前访问的表或派生表。
  • type:访问方式,常见从好到差大致是 consteq_refrefrangeindexALL
  • possible_keys:优化器认为可能用到的索引。
  • key:实际选择的索引。
  • key_len:使用到的索引长度,可辅助判断联合索引用了几列。
  • rows:预计扫描行数,越大风险越高。
  • filtered:预计过滤后剩余比例。
  • Extra:额外信息,比如 Using indexUsing whereUsing filesortUsing temporary

重点不是背字段,而是能通过 Explain 判断:有没有走合适索引、扫描范围是否过大、是否发生额外排序或临时表、联合索引是否用完整。

完整版教学

一、Explain 解决的是什么问题

Explain 用来观察 MySQL 优化器打算怎么执行一条 SQL。它能告诉你访问了哪些表、选了哪个索引、预计扫描多少行、是否需要排序或临时表。

但它不是性能报告。它是优化器基于统计信息做出的估算,可能和真实执行有偏差。真正排查慢 SQL 时,Explain 是入口,还要结合慢日志、真实耗时、数据分布和必要时的 EXPLAIN ANALYZE

面试回答 Explain,要避免背字段表。更好的主线是:这条 SQL 从哪张表开始,怎么访问,每一步预计扫多少数据,过滤后剩多少,是否还要排序、临时表或回表。Explain 像是医生看片子,能看到结构性风险,但不能替代真实体检数据。

看 Explain 的顺序:
table -> type -> possible_keys/key/key_len -> rows/filtered -> Extra

二、type 字段怎么看

type 表示访问方式,是 Explain 里最常被问的字段:

type含义常见场景
const最多匹配一行主键或唯一索引等值
eq_ref联表时每次最多匹配一行被驱动表用唯一索引关联
ref非唯一索引等值匹配普通索引等值查询
range范围扫描between>in
index扫描整个索引全索引扫描
ALL全表扫描没有合适索引或优化器认为全表更划算

不是所有 ALL 都必然错误,小表全表扫描可能很正常;也不是所有 range 都一定好,如果范围很大,扫描成本也会很高。

可以用两个数字例子体会:一张配置表只有 20 行,type=ALL 扫 20 行非常正常;一张订单表 2000 万行,type=rangerows=8000000,仍然可能是慢 SQL。type 表示访问方式,不直接等于性能好坏,必须和数据量、选择性、返回列一起看。

三、key、key_len 和 rows 要一起看

key 表示实际用到的索引。如果 possible_keys 有值但 keyNULL,说明优化器最终没选这些索引,可能是统计信息、选择性或回表成本导致。

key_len 可以辅助判断联合索引用到了哪些列。比如 (a, b, c) 只用了 a,那可能是 b 的条件写法导致索引中断。

rows 是预计扫描行数。优化 SQL 时,最直接的目标通常是减少不必要扫描。如果 rows 很大,即使走了索引,也可能是低效索引扫描。

key_len 常被用来辅助判断联合索引用到了几列,但不要把它当成绝对答案,因为字段类型、是否允许 NULL、字符集都会影响长度。更稳妥的说法是:它能帮助推断索引使用前缀,再结合 SQL 条件和 Extra 判断是否被范围条件、函数或隐式转换截断。

字段组合该看什么典型判断
possible_keys 有,key 为 NULL优化器没选索引可能全表更便宜或统计信息有偏
key 命中但 rows 很大索引选择性不足走索引不等于高效
key_len 偏短联合索引可能只用前几列检查最左前缀和范围条件
filtered 很低后续过滤掉大量记录可能需要更合适的联合索引

易错点:Explain 要成组看字段,单看 typekey 都容易误判。

四、Extra 里的高频信号

常见 Extra 信息:

  • Using index:覆盖索引,查询列可直接从索引返回。
  • Using where:Server 层还要继续判断 where 条件。
  • Using index condition:使用索引下推,存储引擎层先判断部分索引条件。
  • Using filesort:需要额外排序,不一定真的落磁盘,但通常要关注。
  • Using temporary:使用临时表,常见于复杂分组、排序、去重。

Using filesortUsing temporary 不是见到就必须消灭,但如果 SQL 高并发、数据量大,就要重点分析是否能通过索引顺序、改写 SQL 或减少返回数据来优化。

Using filesort 的名字容易误导,它不等于“一定写磁盘文件”,而是表示 MySQL 需要额外排序过程。小结果集排序可能在内存里完成,成本可接受;大结果集排序、高并发排序,才是风险。Using temporary 也类似,复杂 group bydistinct、排序组合都可能触发临时表,要结合行数和频率判断。

-- 如果有索引 (user_id, create_time),这个查询更可能避免额外排序
select *
from orders
where user_id = 1001
order by create_time desc
limit 20;

五、联表 Explain 要看驱动顺序

联表查询还要关注表访问顺序。优化器会选择驱动表和被驱动表,理想情况通常是先用过滤条件强的表缩小结果,再用索引关联另一张表。eq_ref 常出现在被驱动表通过主键或唯一索引关联时,说明每次关联最多匹配一行。

例如订单表和用户表关联,如果先从订单表按时间筛出 100 条,再用用户主键查用户信息,成本很低;如果先扫 1000 万用户再关联订单,就很可能不合理。Explain 的每一行不是孤立看的,行与行之间的访问顺序也很关键。

六、Explain 之后怎么优化

Explain 只是定位方向,不是自动给答案。看到 rows 大,可以考虑更合适的联合索引、条件改写、减少返回列;看到 Using filesort,可以考虑让索引顺序覆盖排序;看到 Using temporary,可以检查分组字段和排序字段是否能减少数据量;看到 key=NULL,要看是否存在函数、隐式转换、前置模糊匹配或统计信息问题。

优化前后要对比同一数据量下的 Explain 和真实耗时。MySQL 8.0 的 EXPLAIN ANALYZE 能给出实际执行统计,但它会真正执行 SQL,在线上使用要谨慎。普通面试回答可以说:Explain 看计划,慢日志看真实慢,必要时压测或在影子环境验证。

七、常见误区与追问

  • 误区:type=ALL 就一定是坏计划。 小表、低选择性查询或返回大部分数据时,全表扫描可能比走索引再大量回表更便宜。
  • 误区:看到 key 有值就说明 SQL 没问题。 还要看 rowsfilteredExtra,低选择性索引扫描大量记录一样会慢。
  • 误区:Using filesort 表示一定发生磁盘文件排序。 它表示额外排序过程,是否落盘取决于数据量、内存和执行情况。
  • 误区:Explain 的 rows 就是真实扫描行数。 它是基于统计信息的估算,可能和真实执行有偏差。
  • 追问:联合索引用了几列怎么看? 可以结合 keykey_len、where 条件和 Extra 推断,但不能只靠 key_len 机械判断。
  • 追问:Explain 优化 SQL 的主线是什么? 看访问路径是否合理、索引是否匹配、扫描行数是否可控、是否有额外排序或临时表,再决定索引和 SQL 改写。

八、加强记忆

Explain 要围绕“访问路径”读:先看访问哪张表,再看 type 判断访问方式,看 key/key_len 判断索引选择和使用前缀,看 rows/filtered 判断扫描与过滤成本,最后看 Extra 捕捉覆盖索引、索引下推、排序和临时表。它是优化入口,不是最终性能结论;真正靠谱的判断,要把执行计划、数据量、慢日志和实际耗时放在一起。