讲解
EXPLAIN 让优化器「说出」它打算怎么执行你的查询,是分析慢查询的第一工具。输出里最该关注的列:type 是访问类型,从好到差大致是 const > eq_ref > ref > range > index > ALL,出现 ALL(全表扫描)且表很大就要警惕;key 是实际使用的索引,NULL 表示没用索引;rows 是优化器估算要扫描的行数;filtered 是条件过滤后剩余比例;Extra 是附加信息,Using index 是好信号(覆盖索引),Using filesort 和 Using temporary 则提示排序、分组没能利用索引。
多表连接时 EXPLAIN 输出多行,第一行是先访问的「驱动表」。优化器通常选过滤后行数少的表当驱动表,连接列有索引的被驱动表会显示 eq_ref 或 ref——两表连接里看到被驱动表是 ALL,基本就是连接列缺索引。
EXPLAIN ANALYZE 是 8.0.18 起的大招:它真的执行查询,并报告每个节点的实际耗时和实际行数,和估算值对比能立刻发现「优化器估错了行数」这类问题。注意它会真的执行——对 SELECT 用没问题,千万别对 UPDATE/DELETE 顺手加一个。需要机器可读格式时用 EXPLAIN FORMAT=JSON,里面包含成本(cost)明细。
示例
重建用户表并造一万行,再加一张两千行的订单表(user_id 上有索引):
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(50) NOT NULL,
city VARCHAR(20) NOT NULL,
age INT NOT NULL
);
CREATE TABLE orders (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
amount DECIMAL(10,2) NOT NULL,
KEY idx_user_id (user_id)
);
SET SESSION cte_max_recursion_depth = 100000;
INSERT INTO users (name, city, age)
WITH RECURSIVE seq AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM seq WHERE n < 10000
)
SELECT CONCAT('user', n), ELT(1 + n MOD 5, '北京', '上海', '广州', '深圳', '杭州'), 18 + n MOD 40
FROM seq;
INSERT INTO orders (user_id, amount)
WITH RECURSIVE seq AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM seq WHERE n < 2000
)
SELECT 1 + n MOD 10000, 10 + n MOD 90 FROM seq;
读一个两表连接的计划:驱动表 orders 因 amount 无索引是 range/ALL,被驱动表 users 走主键 eq_ref——这就是「连接列有索引」的健康形态:
EXPLAIN SELECT u.name, o.amount
FROM orders AS o JOIN users AS u ON u.id = o.user_id
WHERE o.amount > 80\G
EXPLAIN ANALYZE 实际执行并给出真实耗时与行数,对比估算值可以看出优化器靠不靠谱:
EXPLAIN ANALYZE SELECT city, COUNT(*) AS cnt FROM users GROUP BY city ORDER BY cnt DESC LIMIT 3\G
常见坑
- 把 rows 当精确值:rows 是基于统计信息的估算,可能和实际差一个数量级。统计信息过时执行计划就会选错,ANALYZE TABLE 可以刷新。
- 见 ALL 就慌:小表全表扫描比走索引还快,type=ALL 只有在大表上才是问题。判断慢不慢要结合表的实际规模。
- 以为 Using filesort 是写磁盘:filesort 只是「额外排序」的意思,多数在内存完成。它提示排序没用上索引,是否需要优化要看数据量。
- 对写操作用 EXPLAIN ANALYZE:它会真执行。8.0 支持 EXPLAIN ANALYZE 用于 SELECT,也可以用于 INSERT/UPDATE/DELETE——别在生产上试后者。
小结
EXPLAIN 重点看 type(别出 ALL)、key(用上索引)、rows(估算行数)、Extra(Using index 好、filesort/temporary 留意);EXPLAIN ANALYZE 给出真实执行数据。下一章进入另一个核心机制:事务与锁。