SQL中EXPLAIN分析查询性能使用方法(详解执行计划字段解读与type/key/rows/Extra诊断法)

SQL 的 EXPLAIN 是诊断查询性能的”X 光片”——它让数据库优化器把”准备怎么执行这条 SQL”摊开给你看,而不真正跑数据。常规用法是在 SELECT/INSERT/UPDATE/DELETE 前加 EXPLAIN 关键字查看执行计划;MySQL 8.0.18+ 与 PostgreSQL 还支持 EXPLAIN ANALYZE 真正执行并回报实际行数与耗时。据 ramidadboub.com 与腾讯云开发者社区的总结,读懂执行计划的关键只有四列:type(怎么查)、key(用了哪个索引)、rows(预估扫多少行)、Extra(额外干了什么)。只要按”type → key → rows → Extra”的顺序读,绝大多数慢查询的根因都能定位。

一、为什么必须先看 EXPLAIN

一条 SQL 从发起到返回,要经历解析、优化、执行三个阶段,其中优化器生成的执行计划直接决定它是秒回还是卡死。据腾讯云开发者社区的文章,性能瓶颈往往藏在”数据访问方式”里——全表扫描、临时表、额外排序、索引没用上,这些都会在执行计划里一目了然。CSDN 的执行计划实战文章把 EXPLAIN 形容为”X 光片”:没它之前优化靠猜,有它之后优化靠证据。

EXPLAIN 不执行 DML,对生产库安全;EXPLAIN ANALYZE 会真实执行(PostgreSQL 建议在事务里回滚以保安全)。

二、MySQL EXPLAIN 的核心字段

EXPLAIN 输出约 12 列,按重要性分三档(综合 CSDN、cnblogs、OneUptime、ramidabdoub.com):

重要性 字段 含义 关注点
🔴 极高 type 访问类型 ALL 最差,const 最优
🔴 极高 key 实际用的索引 NULL 表示没用索引
🔴 极高 Extra 额外操作 警惕 Using filesort/temporary
🟡 高 rows 预估扫描行数 越小越好
🟡 高 key_len 索引用了几字节 判断联合索引用了几列
🟡 高 possible_keys 候选索引 与 key 不一致需警惕
🟢 中 id / select_type / table 执行顺序、查询类型、表名 多表/子查询定位用

三、type 列:性能风向标

type 是诊断第一眼。它从优到劣排列为:system > const > eq_ref > ref > range > index > ALL(据 techkiz、OneUptime、edsger.dev 一致描述):

  • const / system:主键或唯一索引的精确匹配,最多一行,最优。
  • eq_ref:JOIN 时对方主键/唯一索引匹配,每行最多一条,很好。
  • ref:非唯一索引查找,返回多行,正常。
  • range:索引范围扫描(BETWEEN、IN、>),可接受。
  • index:全索引扫描,比全表好但仍遍历整棵树。
  • ALL:全表扫描,大表上必须优化。

据 ramidadboub.com 的实战示例,一条 WHERE customer_id=250 ORDER BY order_date 若 type=ALL, key=NULL, rows=980000, Extra=Using filesort,就同时暴露”没用索引 + 全扫 + 额外排序”三重问题;加 (customer_id, order_date) 复合索引后,过滤与排序共用一棵树,性能显著回升。

四、key 与 possible_keys:索引选了没

possible_keys 是优化器”考虑过”的候选索引,key 是它”实际选了”的索引。据 ramidadboub.com 解析,二者差异藏着信号:

  • key=NULL 但 possible_keys 有值 → 可能是统计信息过期,跑 ANALYZE TABLE 再试。
  • key=NULL 且 possible_keys 也空 → 要么没建索引,要么函数/类型转换让索引失效(见 13137 篇)。
  • key 不在 possible_keys 中 → 优化器选了更优方案,一般无需干预。

key_len 帮助判断联合索引用了几列:字节数越短,说明只命中了前缀部分列。

五、rows 与 Extra:代价与隐患

rows 是优化器基于统计信息预估的扫描行数,不是实际行数。据 cnblogs 的经验阈值,百万级表期望 rows 控制在千级、千万级表控制在五千级以内;远超则需补索引。filtered(MySQL 5.7+)表示索引查找后 Server 层过滤的剩余百分比,100% 最优。

Extra 是隐患报警器(综合 OneUptime、ramidabdoub.com、腾讯云):

Extra 值 含义 处置
Using index 覆盖索引,无需回表 最优,保持
Using where 索引查找后还需过滤 关注,看能否并入索引
Using index condition 索引条件下推(ICP) 良好,引擎层已过滤
Using filesort 额外排序,ORDER BY 没走索引 加排序列进索引
Using temporary 建了临时表,常见于 GROUP BY 优化索引或拆查询

六、PostgreSQL 的差异:树状计划与成本

PostgreSQL 的 EXPLAIN 不产表格,而是一棵缩进的计划树,最内层节点缩进最深(据 monpg.app 的对照指南)。每个节点带两个数:启动成本与总成本,单位不是毫秒,而是以 seq_page_cost=1.0 为锚的相对成本。关键阅读习惯:

sql

EXPLAIN (ANALYZE, BUFFERS) SELECT ... ;
  • Seq Scan:全表扫描,大表上等于告警,应建索引转 Index Scan。
  • actual rows vs estimated rows:估算与实际差距大 → ���计信息过期,跑 ANALYZE 表。
  • loops=N:嵌套循环内层节点会执行 N 次,实际触碰行数 = rows × loops,忘乘是 PG 读计划的经典错误。
  • Buffers:shared hit 来自缓存、shared read 来自磁盘;多 read 说明缓存未命中。

juejin 的 PG 实践强调:永远加 ANALYZE 和 BUFFERS,DML 用 EXPLAIN ANALYZE 时可包在事务里回滚。

七、标准诊断四步法

把下述顺序作为排查固定动作(综合 ramidadboub.com、cnblogs、CSDN、腾讯云):

  1. 看 type:目标是 ref/range 及以上;出现 ALL 即全表扫描,必须处理。
  2. 看 key:确认非 NULL;若为 NULL,排查缺索引、函数、隐式转换、统计过期。
  3. 看 rows:过大则说明过滤不足,考虑更精确的索引或拆分查询。
  4. 看 Extra:消除 Using filesort 与 Using temporary,优先做成覆盖索引(Using index)。

后续动作:建/改索引后重跑 EXPLAIN 验证,对比 key 是否命中、type 是否提升、rows 是否下降;统计偏差时用 ANALYZE TABLE(MySQL)或 ANALYZE(PG)刷新。

八、EXPLAIN 不是万能

腾讯云开发者社区提醒:执行计划是优化器”此刻基于统计信息”的决策,数据分布、索引状态、系统负载会变,计划也会变。因此分析需结合真实数据量与线上负载动态进行,并在大表结构变更后重新 EXPLAIN。edsger.dev 也给出最佳实践:始终用 EXPLAIN ANALYZE 核对估算与实际的偏差、在类生产数据上测试、统计大变后重新分析。

常见问题(FAQ)

EXPLAIN 会真的执行 SQL 吗?
常规 EXPLAIN 不执行,安全;EXPLAIN ANALYZE 会真实执行,PG 建议包事务回滚。

只看 MySQL 的哪几列就够?
type、key、rows、Extra 四列,按此顺序读即可定位绝大多数问题。

PostgreSQL 的 ANALYZE 和 MySQL 的 ANALYZE TABLE 一样吗?
目的一致(刷新统计信息),但语法不同;都是估算与实际行数偏差大时的首选修复。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
其AI的头像其AI普通用户

相关推荐

返回顶部