我的笔记:怎么用 MySQL 的 EXPLAIN 来分析 SQL


我一直觉得 SQL 慢,大多数时候不是数据库不行,而是我们对执行计划(execution plan)不熟,EXPLAIN 是一个很实用的工具。它就像给 SQL 做一次"体检",能帮我们看到优化空间。


我是怎么理解 EXPLAIN

在我看来,EXPLAIN 就是让数据库把它接下来要怎么执行这条 SQL 告诉你:

  • 它会显示哪些索引被使用了;
  • 它会显示扫描了多少行;
  • 它会显示连接顺序;
  • 还会展示一些额外信息,比如是否要排序、是否使用临时表等等。

举个比喻:你写了个路线规划,EXPLAIN 就是让数据库告诉你它"打算"怎么走这条路线。


基础使用方法

最常见的就是在你的 SELECT 语句前加上 EXPLAIN

sql 复制代码
EXPLAIN SELECT * FROM users WHERE age > 25;

运行之后会返回一张表格,常见字段有:

字段 我理解的含义
id 这是执行步骤的编号
select_type 这个查询是简单查询还是联合查询
table 当前这一行操作的是哪个表
type 最关键 ------ 访问类型,越好越靠前
key 实际使用的索引
rows 估算扫描的行数
Extra 附加信息,比如是否使用文件排序、临时表等

我觉得最值得关注的几项

访问类型 (type)

我自己用的时候,最先盯着这一列看。

从好到差,大致顺序是:

复制代码
const
eq_ref
ref
range
index
ALL

可以这么理解:

  • const/eq_ref:几乎就像直接定位主键,效率最高;
  • ref/range:还算不错,可能用了索引范围扫描;
  • ALL:全表扫描,这就是我们想要避免的。

实际使用的索引 (key)

这一列其实挺直观的:它会告诉你,数据库是不是用了你预期的索引。

举例来说:

sql 复制代码
EXPLAIN SELECT * FROM users WHERE id = 123;

假设你有主键索引 id,那么 key 应该是这条主键索引。

如果 key 显示为 NULL,那就说明没有用索引 ------ 很可能会导致全表扫描。


扫描行数 (rows)

EXPLAIN 会给出一个估算值,表示数据库预计要扫描多少行。

这个其实很关键,因为它能让你直观感受到:

"这个查询要扫描多少数据?"

比如扫描了 100 万行和扫描了 10 行,其性能差距显然是不一样的。


附加信息 (Extra)

这一列包含一些补充信息,我觉得看这一项能帮我发现:

  • 是否用了临时表;
  • 是否做了文件排序;
  • 是否做了索引覆盖等等。

比如如果出现了:

复制代码
Using temporary; Using filesort

这通常说明这个查询在排序或分组时效率不高,这时候我就会考虑:

有没有必要增加合适的索引?


一个简单的例子

假设有这样一张表:

sql 复制代码
CREATE TABLE orders (
    id BIGINT PRIMARY KEY,
    user_id BIGINT,
    amount DECIMAL(10,2),
    created_at DATETIME,
    INDEX idx_user (user_id)
);

我写了两条查询:

sql 复制代码
EXPLAIN SELECT * FROM orders WHERE user_id = 100;

如果输出里面:

  • type: 是 ref
  • key: 是 idx_user
  • rows: 比较小

我觉得这是"合理使用索引"的情况。

再看看:

sql 复制代码
EXPLAIN SELECT * FROM orders ORDER BY amount;

可能出现:

  • key: NULL
  • Extra: Using filesort

说明这条排序没走索引,这时候我就会考虑:

"如果这条查询是常用的,是否应该在 amount 上加一个索引?"


我理解的几个优化思路

基于 EXPLAIN 的输出,我通常会这么判断:

查看是否走索引

key 看成"有没有走索引",没有的话就看是否需要加。

扫描行数是否合理

如果 rows 数特别大,那就说明过滤条件不够好或者没有索引。

注意 Extra 里是否有不良信息

比如:

  • Using temporary
  • Using filesort

这两个我都不太喜欢看到,它们往往意味着性能有提升空间。


我总结几点个人经验

  • 我常常用 EXPLAIN 来调优慢查询;
  • 索引不见得越多越好,但没有关键索引,查询肯定会慢;
  • 同一个 WHERE 条件写法不同,执行计划也可能变化,所以写 SQL 的时候注意表达方式;
  • 多表关联的时候,EXPLAIN 能帮我判断哪个表应该做先驱表(这个在复杂联查里特别重要)。

结语

总的来说,我认为 EXPLAIN 就像是数据库对你说:

我打算怎么执行这条 SQL。

理解它,不是为了背输出字段,而是为了能根据结果判断这条 SQL 有没有优化的空间。

相关推荐
千寻技术帮30 分钟前
10404_基于Web的校园网络安全防御系统
网络·mysql·安全·web安全·springboot
spencer_tseng1 小时前
MySQL table backup
mysql
Z...........1 小时前
MYSQL进阶查询
数据库·mysql
深蓝海拓1 小时前
PySide6从0开始学习的笔记(二十六) 重写Qt窗口对象的事件(QEvent)处理方法
笔记·python·qt·学习·pyqt
中屹指纹浏览器1 小时前
中屹指纹浏览器多场景技术适配与接口封装实践
经验分享·笔记
Dxy12393102163 小时前
MySQL INSERT ... ON DUPLICATE KEY UPDATE 与非主键唯一字段
数据库·mysql
BugShare3 小时前
Obsidian 使用指南:从零开始搭建你的个人知识库
笔记·obsidian
深蓝海拓4 小时前
PySide6从0开始学习的笔记(二十五) Qt窗口对象的生命周期和及时销毁
笔记·python·qt·学习·pyqt
跃渊Yuey4 小时前
【Linux】线程同步与互斥
linux·笔记
AI视觉网奇4 小时前
FBX AnimSequence] 动画长度13与导入帧率30 fps(子帧0.94)不兼容。动画必须与帧边界对齐。
笔记·学习·ue5