RDS for MySQL 慢日志只有耗时?三步定位执行计划
【摘要】 线上 RDS for MySQL 开了慢查询日志,阈值 1 秒,日志里躺着一堆这样的记录:# Query_time: 3.21 Lock_time: 0.00 Rows_examined: 1284392 Rows_sent: 20只有耗时和扫描行数,看不到走了哪个索引、为什么慢,排查全靠猜。其实慢日志的设计就是只记「账单」,不记「路线」——执行计划要自己复现。分享一套三步定位法。 第...
线上 RDS for MySQL 开了慢查询日志,阈值 1 秒,日志里躺着一堆这样的记录:
# Query_time: 3.21 Lock_time: 0.00 Rows_examined: 1284392 Rows_sent: 20
只有耗时和扫描行数,看不到走了哪个索引、为什么慢,排查全靠猜。其实慢日志的设计就是只记「账单」,不记「路线」——执行计划要自己复现。分享一套三步定位法。
第一步:先圈定问题 SQL
在 RDS 控制台「日志管理 → 慢日志」里按耗时排序还不够,重点看扫描行数与返回行数的比值:扫描 128 万行只返回 20 行,说明绝大部分工作量浪费在无效扫描和排序上,这类语句就是优化的主目标。慢日志量大时可以导出后用 pt-query-digest 按 SQL 指纹聚合,按总耗时占比排优先级,避免盯着单条偶发慢查询使劲。
第二步:同参数复现执行计划
拿到完整 SQL 和参数后,在同库执行 EXPLAIN(MySQL 8.0 还可用 EXPLAIN ANALYZE 看每一步的实际耗时)。四个关键列:
- type:出现 ALL 就是全表扫描;
- key:实际命中的索引是不是预期那个;
- rows:优化器预估的扫描行数,和慢日志的 Rows_examined 对得上,才说明复现的是同一个现场;
- Extra:Using filesort、Using temporary 是最常见的两个危险信号。
注意必须用慢日志里的真实参数复现:参数不同、数据分布不同,优化器完全可能选另一条计划,拿着别的参数 EXPLAIN 出来的结论去改索引,只会越改越乱。
第三步:交叉验证,别只信一张计划表
- 查
performance_schema.events_statements_summary_by_digest,看这个 SQL 指纹的累计扫描行、平均耗时,确认它是不是长期作案; - 优化前后对比
SHOW SESSION STATUS LIKE 'Handler_read%'的计数变化,扫描量真的降下来才算改对; - 最后回到慢日志,用同一语句的 Query_time 前后对比收尾验收。
常见根因与对策
| 现象 | 根因 | 对策 |
|---|---|---|
| 扫描百万行返回几十行 | 缺索引或索引列顺序不对 | 等值列在前、范围列在后建联合索引;排序字段能进索引就避免 filesort |
| 索引在、就是不走 | 对索引列用了函数或隐式类型转换 | 改写 SQL,让索引列保持「裸奔」 |
| 计划时好时坏 | 统计信息过期、数据倾斜 | ANALYZE TABLE 更新统计信息 |
| LIMIT 深分页越翻越慢 | 大偏移量扫描丢弃 | 改键集分页(用上次最大 id 做游标) |
慢查询治理的顺序应该是「先定位、再复现、后动手」,而不是看到慢就加索引——加错索引的代价是每次写入都要多维护一棵 B+ 树。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)