文章目录
一、为什么你的SQL跑得比蜗牛还慢?(灵魂拷问时间)
每次点完查询按钮都要刷会儿手机才能出结果?(真实经历警告⚠️)最近排查线上慢查询时,发现有个同事写的关联查询居然跑了8秒!(表数据才20万条啊喂!)结果用EXPLAIN一看——好家伙,全表扫描+文件排序+临时表三连暴击!(血压上来了)
其实90%的性能问题都能通过执行计划分析定位,今天就带大家把EXPLAIN这个神器玩出花!(文末有超实用速查表)
二、EXPLAIN核心参数全解析(看这一part就够了)
2.1 执行计划身份证(id字段)
-- 举个栗子🌰
EXPLAIN
SELECT * FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.age > 18;
当看到多个相同id值时,说明是同一层级查询(比如联合查询)。数字越大执行优先级越高,NULL表示是UNION后的结果集。
2.2 查询类型盲盒(select_type)
常见类型解析表:
| 类型 | 出现场景 | 危险指数 |
|---|---|---|
| SIMPLE | 简单查询(无子查询/UNION) | ⭐ |
| PRIMARY | 外层查询 | ⭐⭐ |
| SUBQUERY | 子查询 | ⭐⭐⭐ |
| DERIVED | 派生表(FROM中的子查询) | 💣 |
| UNION RESULT | UNION合并结果 | ⭐⭐ |
(血泪教训)遇到DERIVED类型要特别注意!之前有个临时表没加索引导致查询直接崩了…
2.3 生死时速type字段(索引使用情况)
性能排序图(建议保存到手机):
system > const > eq_ref > ref > range > index > ALL
举个实战案例:
-- 查询用户最新订单
EXPLAIN
SELECT * FROM orders
WHERE user_id = 10086
ORDER BY create_time DESC
LIMIT 1;
如果type是ref且Extra有"Using filesort",说明虽然用到了索引但排序没走索引,这时候就该考虑(user_id, create_time)的联合索引了!
三、实战优化案例(手撕慢查询)
3.1 案发现场还原
-- 执行耗时:3.8s
SELECT *
FROM products p
LEFT JOIN inventories i ON p.id = i.product_id
WHERE p.category = '电子产品'
AND i.stock > 100
ORDER BY p.price DESC
LIMIT 100;
3.2 EXPLAIN诊断报告
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+-------------+
| 1 | SIMPLE | p | ALL | category_idx | NULL | 200000 | Using where |
| 1 | SIMPLE | i | ref | product_idx | i | 5 | Using where |
+----+-------------+-------+------+---------------+------+---------+-------------+
3.3 问题定位
- products表全表扫描(type=ALL)
- 排序文件排序(Extra没有Using index)
- 关联查询没走覆盖索引
3.4 优化三连击
-- ① 添加联合索引
ALTER TABLE products ADD INDEX category_price_idx (category, price);
-- ② 改写查询(使用覆盖索引)
SELECT p.id, p.name, p.price, i.stock
FROM products p FORCE INDEX(category_price_idx)
INNER JOIN inventories i ON p.id = i.product_id
WHERE p.category = '电子产品'
AND i.stock > 100
ORDER BY p.price DESC
LIMIT 100;
-- ③ 执行计划验证
优化后效果:查询耗时从3.8s → 0.12s!(此处应有掌声👏)
四、EXPLAIN高阶玩法(老司机秘籍)
4.1 JSON格式查看详细执行计划
EXPLAIN FORMAT=JSON
SELECT ...;
会输出完整的成本估算、访问方式等30+个参数(数据分析师狂喜)
4.2 可视化分析工具
推荐使用MySQL Workbench的Visual Explain功能,自动生成执行流程图:
![图示:可视化执行流程图示例]
(虽然不能放图,但你们想象一下树状结构+各种颜色标注就对了)
4.3 索引失效的7个坑
- 隐式类型转换(varchar字段传了int值)
- 索引列使用函数(WHERE YEAR(create_time)=2023)
- 前导模糊查询(LIKE ‘%手机%’)
- OR条件使用不当
- 最左前缀原则违反
- 数据倾斜严重
- 统计信息过期(记得定期ANALYZE TABLE)
五、EXPLAIN速查表(建议打印贴在工位)
| 参数 | 重点关注值 | 优化方向 |
|---|---|---|
| type | 至少达到range级别 | 添加合适索引 |
| rows | 预估扫描行数超过1万 | 优化查询条件 |
| Extra | Using filesort/Using temporary | 调整排序字段或加索引 |
| key_len | 联合索引使用长度 | 检查索引是否充分利用 |
| filtered | 低于10% | 优化WHERE条件选择性 |
六、写在最后(避坑指南)
最近帮实习生排查一个"索引失效"问题,折腾半天发现——他用的测试库根本没创建索引!(真人真事)所以记住:
- 永远要在生产环境相同数据量下验证
- 执行计划只是参考,实际耗时可能有波动
- 定期使用pt-query-digest分析慢日志
- 复杂查询考虑拆分成多个简单查询
下次遇到慢查询别急着甩锅给DBA,自己先掏出EXPLAIN分析一波!(说不定还能在团队分享会上秀一把呢~)
1675

被折叠的 条评论
为什么被折叠?



