生产环境慢 SQL 怎么排查和解决
这道题考的不是背 SQL 语法,而是你有没有 线上救火 的节奏:先止血、再定位、再根治。我按自己习惯的处理顺序写,面试官一般听得懂。
题目
生产环境遇到问题怎么解决?一个查询慢的 SQL,你怎么排查、怎么解决?
参考答案(口述要点)
- 止血:限流、降级、杀慢查询、扩容只读
- 定位:慢日志、APM、
EXPLAIN、锁等待、是否全表扫- 解决:索引、改写 SQL、分页、缓存、归档历史数据
- 复盘:监控告警、上线前压测、规范(禁止 select *、深分页)
详细解析
1. 先确认影响面
- 单接口慢还是 DB CPU 整体飙高?
- 从 网关日志 / SkyWalking / Prometheus 看 P99、错误率
- MySQL:
show full processlist;或performance_schema看谁占着
2. 拿到慢 SQL
# my.cnf 片段
slow_query_log = 1
long_query_time = 1或用 Druid、PMM、云数据库控制台慢 SQL 列表。
3. EXPLAIN(必做)
EXPLAIN SELECT o.*, u.name
FROM orders o
JOIN users u ON o.user_id = u.id
WHERE o.status = 1 AND o.create_time >= '2025-01-01';关注:type 是否 ALL、key 是否用到索引、rows 扫描行数、Extra 是否 Using filesort / Using temporary。
4. 常见原因与对策
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 全表扫 | 无索引、函数破坏索引 | 加联合索引、条件别包 where date(create_time) |
| 扫很多行 | 区分度低、回表多 | 覆盖索引、调整条件 |
| 锁等待 | 长事务、更新顺序 | 拆事务、索引对齐、查 information_schema.innodb_locks |
| 突然变慢 | 统计信息过期 | ANALYZE TABLE;检查是否数据暴涨 |
5. 改写示例
-- 深分页反例
SELECT * FROM orders ORDER BY id LIMIT 1000000, 20;
-- 改为上次最大 id
SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 20;代码与实践
- 项目里对 报表类查询 走从库或 ES,别和交易抢主库。
- 上线 SQL 走 评审 + 预发 EXPLAIN。
- 紧急时先 降级返回缓存旧数据,再慢慢修索引,业务能接受的话。
写在最后
生产问题先 恢复服务 再查根因,别一上来就加索引没评估。面试把这条节奏说出来,比背十条优化技巧更有「老员工」的感觉。
创作不易,转载请注明出处和作者。
