为什么你的SQL这么慢?执行计划分析指南
Mei Lin | 2026-08-20T15:54:00 | Database
MySQL EXPLAIN执行计划完全指南,逐列解析type、key、rows、Extra字段的含义和优化方向
# 为什么你的SQL这么慢?执行计划分析指南 ## 前言 很多开发者写完SQL就直接上线,出了性能问题才想起来看执行计划。今天把EXPLAIN每一列的含义讲清楚,以后写完SQL先EXPLAIN一下再说。 ## EXPLAIN怎么用 ```sql EXPLAIN SELECT * FROM users WHERE age > 25 ORDER BY name; -- 输出示例: -- id | select_type | table | type | key | rows | Extra -- 1 | SIMPLE | users | ALL | NULL | 50000 | Using where; Using filesort ``` ## 关键列解读 ### type列(最重要!) ``` 性能从好到差排列: system > const > eq_ref > ref > range > index > ALL - const: 主键或唯一索引等值查询,最多一行 - eq_ref: JOIN时用主键或唯一索引 - ref: 普通索引等值查询 - range: 索引范围扫描 - index: 全索引扫描(比ALL好,但仍然慢) - ALL: 全表扫描(最差!必须优化) ``` ### Extra列 ``` 重要标识: - Using index -- 覆盖索引,很好! - Using where -- 在server层过滤 - Using filesort -- 文件排序,需要优化ORDER BY - Using temporary -- 使用临时表,需要优化GROUP BY ``` ## 踩坑案例 ### 坑1:索引失效 ```sql -- 对索引列使用函数,索引失效! WHERE YEAR(created_at) = 2024 -- 不走索引 WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01' -- 走索引 -- 隐式类型转换,索引失效! WHERE phone = 13800138000 -- phone是varchar,不走索引 WHERE phone = '13800138000' -- 走索引 ``` ### 坑2:ORDER BY没走索引 ```sql -- 建了索引 (status) -- ORDER BY created_at 不在索引中,会filesort -- 建组合索引 (status, created_at) -- WHERE和ORDER BY都能走索引 ``` ## 快速优化检查清单 1. type是ALL? 加索引 2. Extra有Using filesort? 检查ORDER BY 3. Extra有Using temporary? 检查GROUP BY 4. rows太大? 检查索引选择性 5. key是NULL? 检查索引是否失效 ## 总结 养成写完SQL先EXPLAIN的习惯,90%的慢查询都能在开发阶段发现和优化。