explain用于查看select语句的执行计划,不实际执行(子查询除外);type字段最关键,all最差,理想为range及以上;key与possible_keys不一致需查索引选择性、统计信息或联合索引顺序;extra中using filesort和using temporary共存预示性能严重问题。

直接在 SELECT 前加 EXPLAIN 就能看到执行计划
MySQL 不需要额外安装或开启配置,只要你的查询是 SELECT,在它前面加上 EXPLAIN 关键字,立刻返回执行计划的结构化信息。这不是日志、不是慢查分析,而是优化器“打算怎么执行”的快照——注意,它不真正执行语句(除非 FROM 里有子查询,那部分会被实际执行并写入临时表)。
- 正确写法:
EXPLAIN SELECT * FROM user WHERE id = 123; - 错误写法:
EXPLAIN UPDATE ...或EXPLAIN INSERT ...—— 这些会报语法错误,EXPLAIN只支持SELECT(及DELETE/INSERT/REPLACE的某些变体,但生产中几乎不用,别依赖) - 别用
EXPLAIN FORMAT=JSON初学:虽然更详细,但字段嵌套深、可读性差,先盯住默认表格输出的 10 列,比 JSON 更快定位问题
type 字段决定查询快不快,优先看它是不是 ALL 或 index
type 是执行计划里最敏感的性能信号灯。它告诉你 MySQL 怎么“找数据”:是从整张表扫(ALL),还是走索引跳(ref、eq_ref),或是只查一行(const)。从差到好排序是:ALL → index → range → ref → eq_ref → const。
-
type=ALL:全表扫描,意味着没走索引,或者WHERE条件用了函数/隐式转换(比如WHERE DATE(create_time) = '2025-01-01'),哪怕字段上有索引也废了 -
type=index:比ALL稍好,但仍是遍历整个索引树,常见于SELECT count(*) FROM t(无WHERE)或只查索引覆盖字段但没加WHERE条件 - 目标至少是
range:说明用了索引做范围查找(>=、BETWEEN、IN),再往上ref(等值查非唯一索引)和eq_ref(主键/唯一索引关联)才是健康状态
key 和 possible_keys 对不上?说明优化器放弃了你建的索引
possible_keys 是“候选索引列表”,key 是“最终选中的那个”。两者不一致很常见,但值得深挖原因:
- 索引选择性太低:比如给性别字段(只有 'M'/'F')建了索引,优化器发现走索引还不如全表扫描快,就弃用
- 统计信息过期:
ANALYZE TABLE t;强制刷新行数、索引分布等元数据,有时能“唤醒”被忽略的索引 -
WHERE条件顺序和联合索引顺序不匹配:比如索引是(a,b,c),但查询写了WHERE b = 1 AND c = 2,a没出现,这个索引就无法使用前缀匹配,key会是NULL - 别盲目加索引:
possible_keys里出现多个索引,反而可能说明表设计或查询逻辑有问题(比如字段冗余、条件拆分不当)
别漏看 Extra 里的隐藏开销
Extra 是执行计划的“备注栏”,里面藏着真实性能杀手:
-
Using filesort:MySQL 要额外排序,通常因为ORDER BY字段没走索引,或排序字段和WHERE字段不在同一索引里 -
Using temporary:创建了临时表,常见于GROUP BY+ORDER BY字段不一致、或子查询结果需缓存 -
Using index(注意没有filesort或temporary):这是好消息,表示走了“覆盖索引”,不用回表查数据行 -
Using where:正常现象,说明 MySQL 在存储引擎层之后又做了一次过滤(比如索引只能过滤部分条件,剩余条件靠 Server 层判断)
真正容易被忽略的是:Using filesort 和 Using temporary 同时出现,往往意味着查询已脱离可控范围——这时光调索引没用,得重审业务逻辑是否允许分页改写、聚合下推或结果集裁剪。










