慢 SQL 怎么定位?给出从查看到优化的完整流程。

结论先行:标准流程是“开启慢查询日志 → 抓取分析 → EXPLAIN 看执行计划 → 按索引/改写/结构/参数四层优化 → 上线后对比基线”。没有日志与基线的优化都是盲目的。

一、第一步:把慢 SQL 记录下来

SET GLOBAL slow_query_log = ON;                    -- 开启慢查询日志
SET GLOBAL long_query_time = 1;                    -- 超过 1 秒才记录
SET GLOBAL log_queries_not_using_indexes = ON;     -- 顺带记录没走索引的
mysqldumpslow -s at /var/log/mysql/mysql-slow.log   # 按平均耗时排序
pt-query-digest /var/log/mysql/mysql-slow.log       # 更完整的分析报告

二、第二步:用 EXPLAIN 定位瓶颈

现象可能原因应对
type=ALL全表扫描建合适索引 / 改写条件
rows 巨大扫描范围过大增加过滤、缩小范围
Using filesort排序未走索引联合索引覆盖排序列
Using temporary分组/去重吃紧调整索引或拆分 SQL
锁等待行锁/间隙锁冲突查锁监控,错峰执行

三、第三步:常见优化手段

  • 索引层:为高频 where/order by/group by 设计联合索引,遵循最左前缀。
  • 改写层:去掉 SELECT *,深分页用延迟关联,子查询改 join,杜绝循环查库。
-- 慢:LIMIT 深分页要数过百万行
SELECT * FROM t ORDER BY id LIMIT 1000000, 20;
-- 快:先只取主键再关联回原表
SELECT t.* FROM t JOIN (SELECT id FROM t ORDER BY id LIMIT 1000000, 20) x ON t.id = x.id;
  • 结构层:大字段拆表、冷热数据分离、必要时加汇总表。
  • 参数层:调大 buffer pool、优化临时表内存,前提是前面几层已做完。

常见追问与记忆点

  • 追问:优化完怎么证明有效?对比前后 EXPLAIN 的 rows/Extra 与真实耗时,并跑压测基线。
  • 追问:慢查询日志有副作用吗?有,长期开启要控制 long_query_time 与采样,避免额外 IO。
  • 记忆点:先抓(日志)→ 再看(explain)→ 再改(索引 → 改写 → 结构 → 参数)→ 最后验。
笔记加载中…