Explain 执行计划解读
面试官问:"有一个慢查询,你知道怎么分析吗?"
小马说:"用 EXPLAIN。"
面试官:"好,那 EXPLAIN 输出里 type 列显示 ALL 是什么意思?"
小马:"...全表扫描?"
面试官追问:"那 key_len 怎么算?Using filesort 怎么优化?"
小马开始支支吾吾。
EXPLAIN 是 MySQL 性能优化的基石工具。会用 EXPLAIN 的人和不理解 EXPLAIN 输出的人,在排查慢查询时效率相差十倍以上。今天这篇,把 EXPLAIN 的每个字段全部讲透。
一、EXPLAIN 输出概览 🔴
1.1 基础输出
EXPLAIN SELECT * FROM orders WHERE status = 1;
+----+-------------+--------+------------+------+---------------+-------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+-------+---------+-------+------+----------+-------+
| 1 | SIMPLE | orders | NULL | ref | idx_status | idx_status | 1 | const | 1000 | 100.00 | NULL |
+----+-------------+--------+------------+------+---------------+-------+--------+-------+------+----------+-------+
1.2 各字段含义
1.3 ❌ 错误示范
候选人原话:"type 列 ALL 就是全表扫描,很慢,要优化。"
问题诊断:ALL 不一定慢,要结合 rows 字段判断。如果表只有 100 行,ALL 可能比 ref 更快。优化不是消除 ALL,而是确保合适的场景用合适的访问方式。
候选人原话 2:"Using filesort 就是用了文件排序,很慢。"
问题诊断:filesort 不是"用磁盘文件排序",而是指在内存或磁盘中做额外排序。当数据量小(小于 sort_buffer_size)时,filesort 完全在内存中进行,不涉及磁盘。filesort 的问题是"额外排序步骤",不是"用了磁盘"。
【面试官心理】
EXPLAIN 是 MySQL 面试中出现频率最高的工具题。我通常会问两个层面:一是各字段的含义,二是根据 EXPLAIN 结果判断索引是否有效。很多候选人能背出字段,但不会根据输出做实际判断。
二、type 字段详解 🔴
2.1 type 从好到差排序
常见误区:index 和 ALL 都要扫描很多数据,但 index 扫描的是索引树而不是数据树。如果索引包含查询的所有字段,index 可能比 ALL 快(因为索引文件通常比数据文件小)。
2.2 常见 type 场景分析
-- const: 主键等值查询
SELECT * FROM orders WHERE id = 10086; -- type: const
-- ref: 普通索引等值查询
SELECT * FROM orders WHERE status = 1; -- type: ref
-- range: 范围查询
SELECT * FROM orders WHERE status > 1; -- type: range
SELECT * FROM orders WHERE status IN (1, 2, 3); -- type: range
-- eq_ref: 联表查询,被驱动表用主键访问
SELECT * FROM orders o JOIN users u ON o.user_id = u.id; -- u 表: type: eq_ref
-- index: 查询覆盖索引,但需要扫描整个索引
SELECT status FROM orders; -- type: index
-- ALL: 全表扫描
SELECT * FROM orders WHERE amount > 100; -- 无索引: type: ALL
2.3 优化目标
const / eq_ref:极致,大多数 OLTP 查询应达到
ref:良好,普通索引查询的正常水平
range:可接受,范围查询的正常表现
index:警告,检查是否可以覆盖索引优化
ALL:必须优化,尽量建立合适的索引
3.2 Using filesort 详解
filesort 不是"用磁盘文件排序",而是"在拿到数据后需要额外排序"。
-- 需要 filesort
SELECT * FROM orders WHERE status = 1 ORDER BY created_at DESC;
-- 索引 idx(status, created_at) 可以覆盖此查询,不需 filesort
-- 如果没有这个索引,MySQL 会按 status 查出来,再按 created_at 排序
-- 不需要 filesort
SELECT * FROM orders WHERE status = 1 ORDER BY id DESC;
-- 如果主键索引包含在查询结果中,且索引有序
filesort 优化方法:
- 建立合适的索引:
ORDER BY 的字段在索引中且满足最左前缀
- 减少排序数据量:加
WHERE 条件,缩小排序范围
- 增加 sort_buffer_size:增加内存排序区,减少磁盘排序
3.3 Using temporary 详解
-- 需要临时表
SELECT status, COUNT(*) FROM orders GROUP BY status;
-- MySQL 会创建临时表存储中间结果,再聚合
-- 不需要临时表
SELECT status, COUNT(*) FROM orders WHERE status = 1 GROUP BY status;
-- 缩小范围后可能直接在索引中完成
四、key_len 计算 🟡
4.1 key_len 的含义
key_len 表示索引使用的字节数,可以用来判断联合索引使用了多少列。
-- 表结构
-- id: BIGINT (8字节)
-- name: VARCHAR(32) 字符集 utf8mb4(每个字符 4 字节)
-- age: TINYINT (1 字节)
-- 索引: idx(id, name, age)
-- 查询: WHERE id = 1
-- key_len = 8 (只用了一列 id)
-- 查询: WHERE id = 1 AND name = 'Tom'
-- key_len = 8 + 32*4 = 136 (id + name,但 VARCHAR 需要存长度)
-- 精确计算: 8 + (32*4 + 2) = 142 (VARCHAR 头 2 字节存长度)
-- 查询: WHERE id = 1 AND name = 'Tom' AND age = 25
-- key_len = 8 + (32*4 + 2) + 1 = 143
4.2 通过 key_len 判断索引使用情况
-- 索引 idx(a, b, c)
-- EXPLAIN 显示 key_len = 4
-- 判断:用了几列?
-- a 是 INT (4字节) → 用了一列
-- b 是 VARCHAR(10) → 如果用了,key_len 至少 10*4+2 = 42
-- 结论:只用了一列 a
五、生产实战 🟡
5.1 慢查询排查流程
-- Step 1: 开启慢查询日志
SHOW VARIABLES LIKE 'slow_query%';
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 超过 1 秒记录
-- Step 2: 查看慢查询
SHOW GLOBAL STATUS LIKE 'Slow_queries';
-- Step 3: 分析执行计划
EXPLAIN SELECT ...
-- Step 4: 查看详细执行信息
EXPLAIN ANALYZE SELECT ... -- MySQL 8.0+
5.2 联合查询的 EXPLAIN
EXPLAIN SELECT o.*, u.name
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 1;
-- 关键字段分析:
-- type: o 表应该是 ref 或 range,u 表应该是 eq_ref(主键访问)
-- key: o 表应该用 idx_status,u 表应该用 PRIMARY
-- rows: 评估扫描行数
💡
EXPLAIN ANALYZE(MySQL 8.0+)比 EXPLAIN 更进一步,它会实际执行查询并显示真实的耗时和行数,是更精确的性能分析工具。
【面试官心理】
问 EXPLAIN 的候选人里,能说出 type 和 Extra 的常见值的是大多数。能说出 key_len 计算方法的就不多了。能根据一个 EXPLAIN 输出判断索引设计是否合理、SQL 是否需要优化的,是真正有实战经验的候选人。