慢查询日志与优化
2024年双十一前夜,订单服务报警:接口响应时间从 50ms 飙到 5s。
DBA 排查发现,一条看似简单的 SQL 要执行 3 秒:
开发同学说:"我加了索引的啊!"DBA 一看执行计划,type=ALL,全表扫描 500 万行。
索引确实加了,但建在了 status 字段上,而这个查询没有 status 条件。
【面试官心理】 这道题我用来测试候选人有没有完整的 SQL 优化经验。能找到慢查询的占 50%,能分析执行计划的占 30%,能从索引设计层面解决问题的占 10%。慢查询优化是生产环境最常见的问题,也是最能体现工程师功力的场景。
一、慢查询的发现与配置 🔴
1.1 开启慢查询日志
1.2 慢查询日志格式
关键字段:
⚠️
Rows_examined 是判断查询效率的核心指标。同样是查 20 行,扫描 5000 行和扫描 500 万行的效率差 1000 倍。
1.3 pt-query-digest 分析工具
二、慢查询的分析流程 🟡
2.1 五步定位法
2.2 案例:用户订单列表查询
原始 SQL:
执行计划分析:
问题诊断:
- orders 表扫描 5000 行(太多)
- Using filesort 需要额外排序
- 需要回表取所有字段
2.3 优化方案
优化效果:
- rows 从 5000 降到 50
- Using filesort 消失
- Using index 出现(覆盖索引生效)
三、常见慢查询模式 🟡
3.1 分页查询深度分页
原因:MySQL 需要先排序,再跳过 100 万行。
优化方案 1:游标分页
优化方案 2:延迟关联
3.2 COUNT(*) 统计慢
3.3 JOIN 导致的慢查询
💡
MySQL 优化器会自动选择小表驱动大表,但有时会选错。用 STRAIGHT_JOIN 强制指定驱动表顺序。
四、生产优化 Checklist 🟡
4.1 索引优化
- 确保 WHERE 条件字段有索引
- 确保 ORDER BY 字段在索引中(且方向一致)
- 确保 SELECT 字段在覆盖索引中
- 避免索引失效(函数、隐式转换、最左前缀)
4.2 查询优化
- 避免 SELECT *,明确列出需要的字段
- 用 LIMIT 限制返回行数
- 用游标分页替代 OFFSET 分页
- 避免深度嵌套子查询
4.3 监控告警
【面试官心理】 我问他慢查询优化,通常还会追问:生产环境中怎么发现慢查询、多长时间优化一次、怎么验证优化效果。能给出完整流程的,基本都有实际踩坑经验。