EXPLAIN 执行计划:一眼看穿你的SQL慢在哪

本文涉及的产品
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS Agent Manager,2核4GB
PolarDB Agent Express,2核4GB
简介: 数据库小学妹带你轻松掌握SQL性能诊断!通过EXPLAIN查看执行计划,精准识别索引失效、全表扫描(ALL)、key为NULL等瓶颈。聚焦type、key、rows等6个关键字段,结合实战案例与避坑指南(如函数滥用、最左前缀破坏),让优化有的放矢。学完即用,告别盲目调优!

📌 今日关键词: 执行计划、Explain、SQL优化、索引失效、性能诊断

大家好呀!我是​数据库小学妹​👋

我们之前学过​索引​,也分享过​SQL优化十大技巧​。但是在使用索引的过程我常遇到这些问题:

我怎么知道​索引有没有生效​?为什么加了索引还是慢?这条查询到底慢在哪一步?

每次遇到慢查询,我都像无头苍蝇一样乱试:加索引、改SQL、拆表……运气好能蒙对,运气不好折腾半天。

后来同事告诉我:光建索引不行,你得学会看SQL的“体检报告”,我们今天要学的就是数据库的“诊断报告”——​执行计划​。把SQL丢进去,它就会告诉你数据库打算怎么查、用没用索引、扫了多少行。精准定位查询瓶颈,不再瞎优化!

一、什么是执行计划?

执行计划是数据库为了执行你的SQL,自己制定的“作战方案”。它会告诉你:

  • 什么顺序访问表
  • 用​哪个索引​(或者不用)
  • 预计要扫描多少行
  • 需不需要​临时表​、文件排序

如何查看? 很简单,在SELECT前面加上 EXPLAIN 就行了:

EXPLAIN SELECT * FROM users WHERE age > 18;

执行后,MySQL会返回一张表格,每一行代表一个“步骤”。看懂这张表,你就知道SQL慢在哪了。

💡 EXPLAIN 不会真正执行SQL,只是分析查询计划,所以放心用,不会改数据。

二、执行计划结果中6个关键字段

虽然 EXPLAIN 返回的字段很多,但我们新手只需要关注​6个关键字段​,就能解决90%的问题:

⭐ id:执行顺序的“优先级”

  • 含义: 查询中操作表的顺序标识。
  • 怎么看: 数字越大,越先执行;数字相同,从上往下执行。
  • 避坑: 如果你在写复杂的子查询,id 能帮你判断哪个子查询是“老大”。

⭐select_type:查询的“身份”

  • SIMPLE:简单的查询(没有子查询或UNION)。
  • PRIMARY:最外层的查询。
  • SUBQUERY:子查询中的第一个 SELECT。
  • 理解它: 知道自己写的是简单查询还是复杂嵌套,有助于分析性能。

⭐table:正在操作的“对象”

  • 含义: 这一行操作的是哪张表。
  • 技巧: 在多表关联时,这里会显示表名,配合 type 字段看关联效率。

⭐type:访问类型的“含金量”(最重要!)

这是判断SQL性能好坏的金标准。从最好到最差:

  • system/const:完美! 通过主键或唯一索引直接命中,速度极快。
  • eq_ref:优秀! 通常出现在多表关联的主键匹配中。
  • ref:良好! 使用了非唯一索引进行等值查询。
  • range:凑合! 使用了索引进行范围查询(如 BETWEEN, IN)。
  • index:警告! 索引全扫描。虽然走了索引,但还是把索引树遍历了一遍。
  • ALL:危险! 全表扫描!这是性能杀手,必须优化。

小学妹口诀: 能 const 就不 range,千万别出现 ALL!

⭐ possible_keys & key:索引的“博弈”

  • possible_keys:理论上可能用到的索引。
  • key:实际上真正用到的索引。
  • 避坑: 如果 possible_keys 有值,但 key 是 NULL,说明索引失效了! 这就是你需要排查的地方。

⭐rows:预计扫描的“行数”

  • 含义: 数据库预估要扫描多少行才能找到数据。
  • 目标: 这个数字越小越好。如果是百万级的表,这里显示几万,那肯定有问题。

三、实战:用Explain诊断“慢SQL”

场景: 我们有一张orders表(订单表),数据量很大。我想查用户ID为100的所有订单。

  1. 建表示例
CREATE TABLE orders (
    id INT PRIMARY KEY,
    user_id INT,
    amount DECIMAL(10,2),
    create_time DATETIME
);
-- 假设我们忘了给 user_id 加索引
  1. 慢SQL诊断
EXPLAIN SELECT * FROM orders WHERE user_id = 100;

报告分析:

🚨 诊断结果:

  • type: ALL:全表扫描!数据库正在一行一行地翻找。
  • key: NULL:没有用到任何索引。
  • rows: 1000000:扫描了100万行!这太慢了。
  1. 优化方案 给 user_id 加个索引,再跑一次 EXPLAIN:
CREATE INDEX idx_user_id ON orders(user_id);
EXPLAIN SELECT * FROM orders WHERE user_id = 100;

优化后报告:

✅ 优化结果:

  • type: ref:使用了索引!
  • key: idx_user_id:命中了我们刚建的索引。
  • rows: 5:只扫描了5行数据!🚀 这就是 EXPLAIN 的魔力!

四、新手避坑指南

💢对字段使用了函数:

  • 错误: WHERE YEAR(create_time) = 2023
  • 原因: 数据库无法直接用索引,必须把所有时间拿出来算一遍年份。
  • 修正: WHERE create_time BETWEEN '2023-01-01' AND '2023-12-31'

💢最左前缀原则破坏:

  • 场景: 你建了联合索引 (a, b, c),但查询条件只写了 WHERE b = 1 AND c = 2。
  • 结果: 索引失效(除非是覆盖索引)。
  • 修正: 查询条件必须包含最左边的字段 a。

💢隐式类型转换:

  • 错误: user_id 是 INT 类型,但你写了 WHERE user_id = '100'(加了引号)。
  • 原因: 数据库会把数字转成字符串比较,导致索引失效。
  • 修正: 保持类型一致,WHERE user_id = 100。

五、今日学习心得

今天的内容总结成三句话:

  1. EXPLAIN 是慢查询的“CT机”​,用之前不要乱加索引
  2. 重点关注 type(ALL要优化)、key(是否为NULL)、Extra(有无临时表/文件排序)
  3. 优化后一定重新 EXPLAIN​,验证是否生效

👋 我是数据库小学妹一个用设计师思维学数据库的转行人。我们一起,把复杂的技术变得简单有趣!💕

本文示例基于 MySQL 8.0。EXPLAIN 在不同版本中细节有差异,但核心思想通用。

相关文章
|
1月前
|
SQL 关系型数据库 MySQL
MySQL主从复制实战:从原理到读写分离,新手避坑全指南
数据库小学妹带你轻松入门主从复制!✅基于binlog实现主库写、从库读,支撑读写分离与高可用;🛡️保障数据安全(灾备)、提升并发能力;🔧详解三种复制模式、搭建步骤、延迟优化及避坑指南。运维进阶必备!
|
1月前
|
SQL 关系型数据库 MySQL
MySQL慢查询诊断实战:从10秒到0.1秒,我的5步排障法
数据库小学妹分享慢查询优化实战:从10秒降至0.08秒!详解「发现→收集→分析→优化→验证」5步排障法,覆盖慢日志配置、EXPLAIN进阶、索引失效场景、JOIN与分页优化等核心技巧,附真实案例与速查表。
|
2月前
|
存储 数据采集 分布式计算
数据仓库是什么?数据仓库和大数据平台、数据湖、数据中台、湖仓一体有什么区别?
本文厘清数据仓库、大数据平台、数据湖、数据中台、湖仓一体五大核心概念的本质区别与适用场景,破除术语混淆误区。从架构定位、数据类型、建模方式、技术演进到典型优劣,逐一剖析,助你精准选型、科学设计、自信汇报。
|
1月前
|
SQL 关系型数据库 MySQL
【MySQL百日打怪升级第14天】 LIMIT 分页的性能优化:深分页到底慢在哪?
本文深入剖析MySQL深分页(如`LIMIT 100000,20`)性能瓶颈:本质是OFFSET导致全量扫描与丢弃,页码越深,扫描行数线性增长。详解三种实战优化方案——游标分页(高效稳定,需有序唯一字段)、延迟关联(兼容OFFSET,索引覆盖减回表)、范围分页(极简但场景受限),并附EXPLAIN对比与避坑指南。(239字)
227 6
|
人工智能 运维 关系型数据库
智能运维+多模型服务能力,阿里云 RDS AI 助手旗舰版正式上线!
RDS AI 助手旗舰版在 RDS AI 助手专业版智能运维能力的基础上,提供灵活模型选择、智能模型路由、多模型灾备、API Key 集成等更自主可控、灵活便捷的模型服务,并支持纳管运维各类环境部署的数据库。
智能运维+多模型服务能力,阿里云 RDS AI 助手旗舰版正式上线!
|
1月前
|
关系型数据库 MySQL 测试技术
JOIN、IN、EXISTS谁最快?实测三种写法性能差异与执行计划深度剖析
本文用MySQL 8.0实测拆解`IN`/`EXISTS`/`JOIN`子查询性能:从执行计划、半连接优化、临时表开销等底层原理出发,结合10万+100万数据实测(`EXISTS`最快95ms),给出三条选型铁律——告别盲从“最佳实践”,只选最适配业务与数据的写法!
|
2月前
|
SQL 关系型数据库 MySQL
SQL优化十大技巧,查询速度提升10倍!
数据库小学妹带你轻松提速SQL!10个实战优化技巧:精简SELECT、善用LIMIT、巧用EXPLAIN、合理建索引、避开函数索引失效、JOIN优于子查询、IN替代OR、批量操作、EXISTS优化大子查询、定期OPTIMIZE。附避坑指南,新手也能秒上手!
|
2月前
|
编解码 缓存 API
【开源剪映小助手】草稿管理接口
本文档详解剪映草稿管理三大核心API:创建、保存及获取草稿文件列表,涵盖请求参数、响应格式、错误码、URL规则与最佳实践,助力开发者快速集成稳定高效的草稿系统。(239字)
|
19天前
|
SQL 监控 关系型数据库
数据库三大日志深度解析:Redo Log、Binlog、Undo Log 如何守护你的数据
本文由“数据库小学妹”带你厘清MySQL三大核心日志:Redo Log(引擎层物理日志,保障crash-safe)、Undo Log(支撑回滚与MVCC)和Binlog(Server层逻辑日志,用于复制与恢复),详解WAL机制与两阶段提交原理,助你真正理解事务安全底层逻辑。
|
1月前
|
SQL Java 中间件
读写分离与查询路由实战:从原理到Spring Boot代码实现
本文由“数据库小学妹”详解读写分离与查询路由实战:基于Spring Boot + 动态数据源(AbstractRoutingDataSource + AOP)实现主从库自动分流;对比ShardingSphere等中间件方案;涵盖强制读主、延迟感知、负载均衡等路由策略及避坑指南。