-
- [我是怎么理解 `EXPLAIN` 的](#我是怎么理解
EXPLAIN的) - 基础使用方法
- 我觉得最值得关注的几项
- 一个简单的例子
- 我理解的几个优化思路
- 我总结几点个人经验
- 结语
- [我是怎么理解 `EXPLAIN` 的](#我是怎么理解

我一直觉得 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: 是refkey: 是idx_userrows: 比较小
我觉得这是"合理使用索引"的情况。
再看看:
sql
EXPLAIN SELECT * FROM orders ORDER BY amount;
可能出现:
key: NULLExtra: Using filesort
说明这条排序没走索引,这时候我就会考虑:
"如果这条查询是常用的,是否应该在 amount 上加一个索引?"
我理解的几个优化思路
基于 EXPLAIN 的输出,我通常会这么判断:
查看是否走索引
把 key 看成"有没有走索引",没有的话就看是否需要加。
扫描行数是否合理
如果 rows 数特别大,那就说明过滤条件不够好或者没有索引。
注意 Extra 里是否有不良信息
比如:
Using temporaryUsing filesort
这两个我都不太喜欢看到,它们往往意味着性能有提升空间。
我总结几点个人经验
- 我常常用
EXPLAIN来调优慢查询; - 索引不见得越多越好,但没有关键索引,查询肯定会慢;
- 同一个
WHERE条件写法不同,执行计划也可能变化,所以写 SQL 的时候注意表达方式; - 多表关联的时候,
EXPLAIN能帮我判断哪个表应该做先驱表(这个在复杂联查里特别重要)。
结语
总的来说,我认为 EXPLAIN 就像是数据库对你说:
我打算怎么执行这条 SQL。
理解它,不是为了背输出字段,而是为了能根据结果判断这条 SQL 有没有优化的空间。