我的笔记:怎么用 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 有没有优化的空间。

相关推荐
克里斯蒂亚诺更新5 小时前
ruoyi角色权限的对应关系
笔记
Database_Cool_6 小时前
OLTP 和 OLAP 区别详解:分析型数据库和事务型数据库怎么选(附阿里云 AnalyticDB MySQL 选型指南)
数据库·mysql·阿里云
Database_Cool_7 小时前
单机 MySQL 迁移到分布式数据库方便吗?阿里云 PolarDB-X 100% MySQL 协议兼容零改造平滑迁移
数据库·分布式·mysql
姜太小白8 小时前
【MySQL】 索引优化实战:解决 WHERE 等值 + IS NULL 查询,TEXT 字段报错 1167 的完整指南
数据库·mysql
a1117768 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
liuxiaowei39 小时前
【绝版教程】新版MySQL DBA高级实战进阶班 MySQL8.0 姜承尧-腾讯数据库总监
数据库·mysql·dba
破碎的南瓜9 小时前
sqli--sql注入过关笔记(1,2,3,4,5,9)
数据库·笔记·sql
你想知道什么?10 小时前
线性回归-学习笔记
笔记·学习·线性回归
谙弆悕博士10 小时前
系统集成项目管理工程师教程(第3版)笔记——第17章:法律法规和标准规范
笔记·职场和发展·学习方法·业界资讯·软考·法律·法规
Csvn11 小时前
📊 SQL 入门 Day 10:递归 CTE — 破解无限层级查询的终极武器
后端·sql