北京华为云代理商总结:碰到 RDS 慢查询暴涨,如何借助执行计划找根源
华为云RDS MySQL慢查询突增:执行计划分析指南
业务高峰期,华为云RDS MySQL实例突然出现大量慢查询,接口响应时间从几十毫秒拉长到几秒,告警邮件连续触发。这类“RDS MySQL慢查询突增分析”场景下,多数人的第一反应是升级CPU或内存,但更常见的情况是执行计划悄悄变了。先别急着扩容,从慢查询的定义和突增的常见诱因入手,能更快锁定问题SQL。
慢查询突增背后的原因?
什么是慢查询?
慢查询不是绝对意义上的“慢”,而是指执行时间超过了预设阈值的SQL语句。MySQL默认的long_query_time是10秒,但生产环境通常建议调整为1~2秒,因为10秒的阈值会漏掉大量已经影响业务的查询。在华为云RDS控制台里,这个参数可以按实例调整,调整后配合慢查询日志或SQL洞察,才能捕捉到真正拖慢接口的语句。判断一条SQL慢不慢,不能只看单次执行时间,还要结合执行频率和锁等待时间。如果一条SQL执行了0.5秒,但每秒执行几百次,累积效应同样能把数据库拖垮。

为什么会出现突增?
慢查询突增的典型原因不是CPU突然不够用,而是执行计划发生了劣化。比如表数据量增长后,统计信息没有及时更新,优化器错误地选择了全表扫描,type从ref退化成ALL,rows预估扫描行数从几百跳到几十万,单条SQL耗时就会从毫秒级飙升到秒级。另一种常见情况是索引突然失效,比如隐式类型转换、对索引列使用函数或前导模糊查询,都会让原本走索引的SQL改走全表扫描。这些变化往往是突发的,因为业务数据量、更新比例或查询条件组合在某个时间点越过了优化器的阈值。
哪些场景容易触发突增?
突增并不总是与业务量线性相关。聚搜云在整理这类服务器故障时发现,RDS MySQL慢查询突增多发生在三种场景:一是大表新增了不带索引的查询字段,或者新上线的业务SQL直接扫大表;二是定时任务或批处理在低峰期执行,但执行计划错误导致全表扫描,拖累整个实例;三是统计信息过期,优化器对数据分布判断失真,比如一张表从几万行增长到几百万行后,优化器还以为是小表,继续选全表扫描。这些场景的共同点是:问题SQL之前未必慢,是执行计划随数据变化而突然变坏。
如何获取执行计划?
慢查询突增时,第一步不是急着加索引或扩配置,而是先拿到慢 SQL 的执行计划,确认优化器到底选择了哪条路径。从聚搜云接触到的企业运维场景来看,多数 RDS MySQL 慢查询问题最后都能归结为执行计划里 type=ALL、rows 预估过大或 Extra 出现 Using filesort 这几类情况。在华为云 RDS MySQL 环境中,获取执行计划主要有三条路径:直接对目标 SQL 使用 EXPLAIN、从慢查询日志中提取历史 SQL 再分析,以及在问题发生当下实时抓取正在执行的慢语句。下面分别展开。
使用 EXPLAIN 命令
EXPLAIN 是最直接的手段,拿到疑似慢 SQL 后,在 MySQL 客户端执行 EXPLAIN SELECT ... 即可。重点看四列:type 是否出现 ALL 或 index,key 是否为空或与预期索引不一致,rows 是否远超过实际返回行数,Extra 是否出现 Using temporary、Using filesort。例如 type=ALL 且 rows 达到几十万行,基本可以判定全表扫描是慢查询主因。MySQL 8.0 还支持 EXPLAIN ANALYZE,能返回实际执行行数和耗时,比预估计划更可靠。
查看慢查询日志
慢查询日志是慢 SQL 的“存档”。生产环境建议将 long_query_time 设置为 1~2 秒,并开启 log_output=TABLE,这样可直接查询 mysql.slow_log 表,避免频繁解析文件。华为云 RDS MySQL 控制台的“慢日志”页面已经做了聚合和排序,能按执行次数、平均耗时定位 Top SQL。注意默认阈值是 10 秒,如果没调整过,很多 2~5 秒的潜在慢 SQL 不会被记录,导致故障发生时只能看到已经恶化的语句。

实时抓取慢 SQL
突增场景下,慢日志可能有滞后,此时要实时抓正在执行的慢语句。最常用的是 SHOW FULL PROCESSLIST,或查询 information_schema.processlist 过滤 COMMAND='Query' AND TIME>1。更精准的方式是查 performance_schema.events_statements_current,它能拿到 SQL 文本和执行时间,但需要提前开启相关 instruments。华为云 RDS 的“SQL 洞察”功能相当于把这些实时数据做了可视化,建议优先在控制台查看全量 SQL 记录,再配合 EXPLAIN 分析,比命令行逐条抓取效率高得多。
执行计划解读要点?
在华为云 RDS MySQL 慢查询突增分析中,抓到具体 SQL 后,先别急着加索引。EXPLAIN 输出决定了这条 SQL 卡在访问路径还是数据量。从聚搜云接触到的企业运维场景来看,不少慢查询最终不是“没索引”,而是优化器选错索引或低估回表代价。下面按 type/key、rows/filtered、EXTENDED 三个方向拆开看。
读懂 type 与 key
type 表示访问类型,从 system 到 ALL 依次变差。遇到 type=ALL 且 key=NULL 时,基本是全表扫描;但如果 type=ref 而 key 指向低区分度索引,rows 依然可能很大。比如在千万级订单表上,WHERE status=1 走 idx_status 会返回 400 万行,比全表扫描还差。所以不能只看 type 不是 ALL 就放过,要结合 key 的实际选择性判断。
关注 rows 与 filtered
rows 是优化器预估扫描行数,filtered 是经过 WHERE 后剩余行比例。两者相乘才是真正返回给上层的数据量。遇到 rows=50 万、filtered=10 时,实际返回 5 万行,但如果回表 5 万次,随机 IO 开销比全表扫描更大。此时可在测试库执行 EXPLAIN ANALYZE,用 actual rows 对比预估 rows,偏差超过一个数量级就应 ANALYZE TABLE 更新统计信息。
使用 EXTENDED 分析
老版本 MySQL 的 EXPLAIN EXTENDED 在 5.7 后已并入标准 EXPLAIN,8.0 直接移除 EXTENDED 关键字。需要看优化器重写结果时,执行 EXPLAIN FORMAT=JSON 或 EXPLAIN 后接 SHOW WARNINGS。重点查看 attached_condition 和 possible_keys,例如前置模糊 LIKE '%202506%' 会显示 using_where,说明无法走普通索引,应改用全文索引或函数索引,而不是继续堆普通索引。
优化执行计划的常用方法?
索引优化与添加
看到 type=ALL 或 rows 预估扫描几十万行时,先确认过滤条件是否真的能命中索引,而不是直接建索引。复合索引必须遵循最左前缀,(a,b,c) 可覆盖 (a)、(a,b)、(a,b,c) 三种查询,单独查 b 或 c 不会走该索引。建索引时把区分度高的列放前面,比如 update_time 与状态字段组合时,优先用 update_time 驱动范围扫描。加完索引后用 EXPLAIN 对比 key 与 rows 的变化,Using index condition 也可能存在回表压力,不能只看 type 是否变好。
改写SQL语句
慢查询突增时,SQL 写法问题往往比缺索引更隐蔽。SELECT * 会把大字段全部拉出,即使走索引也会因回表过多拖慢;LIKE '%xx%' 前置模糊查询无法走 B+ 树索引;对索引列套函数如 DATE(create_time) 同样会让索引失效。改写时优先让 Extra 出现 Using index 而不是 Using filesort,减少临时表与排序。从聚搜云接触到的企业运维场景来看,很多执行计划劣化并不是统计信息的问题,而是 SQL 本身允许了全表扫描或强制回表。

调整表结构
当单表数据超过千万行且慢查询集中在范围扫描或排序时,单纯加索引的收益会快速下降。可以按业务时间维度做分区或归档历史数据,缩小扫描范围;也可以把高频过滤字段冗余到主表,避免多表 join 产生临时表。在华为云 RDS MySQL 上调整表结构要避开业务高峰期,并使用在线 DDL 工具降低锁表影响。调整后需执行 ANALYZE TABLE 更新统计信息,再通过 EXPLAIN ANALYZE 确认实际执行路径是否稳定,而不是仅看预估 rows。
华为云RDS专用优化工具?
慢查询突增时,先在华为云RDS控制台里用工具收敛范围,比登录服务器翻慢日志更直接。这些工具并不直接优化SQL,更多是把故障范围从“数据库慢”压缩到具体SQL和指标。从聚搜云接触到的企业运维场景来看,不少华为云代理商的代维团队也是先通过监控确认突增时间点,再拉诊断报告定位SQL,最后才进入EXPLAIN分析。下面按使用顺序说三个工具。
云监控告警设置
不要等到业务报障才看监控。RDS实例的“云监控”里把慢查询数和CPU使用率设成两个独立告警:慢查询数>30次/5分钟或CPU>80%持续5分钟触发。阈值别设成1次/分钟,否则偶发抖动会淹没告警。触发后先看时间点和指标曲线,确认是单点突增还是持续爬坡,再决定是否进SQL洞察拉取明细。
诊断报告生成
进入“诊断报告”选择故障时间段,RDS会按执行次数和平均耗时列出Top SQL。这里重点看两个指标:扫描行数除以返回行数是否偏高,以及同一SQL在突增前后执行计划是否变化。把Top SQL文本抓出来后不要直接改,先在客户端或命令行用EXPLAIN FORMAT=JSON确认实际访问路径,再考虑是否加索引或重写。
自动优化建议
RDS给出的索引建议可以参考,但不建议一键应用。它经常对高写入表建议加索引,容易拖慢写入并增加存储开销。先核对建议索引与现有复合索引是否重复,再用EXPLAIN ANALYZE在从库或低峰验证实际执行时间和扫描行数。对慢查询突增来说,自动建议更适合兜底排查,不是主修复方案。

实战案例:突增处理全流程
案例背景与现象
某企业核心业务库部署在华为云RDS MySQL 8.0,实例规格8C32G,日常慢查询阈值调整为1秒。某日下午业务群反馈订单查询明显变慢,监控显示慢查询数从每分钟2-5条短时升至40条以上,CPU使用率由35%冲到85%,但IOPS和连接数未明显上涨。从北京华为云代理商聚搜云整理的运维案例来看,这种情况优先怀疑有SQL执行计划劣化,而不是实例资源本身吃紧。
分析定位过程
先通过华为云控制台的SQL洞察功能,按执行耗时倒序抓取到一条高频查询:SELECT o.id, o.order_no, c.name, o.amount FROM orders o JOIN customer c ON o.cid = c.id WHERE o.status = 'PAID' AND o.created_at > '2025-01-01' ORDER BY o.created_at DESC LIMIT 50;。该语句平均执行时间从0.2秒恶化到6秒以上。随后在测试库执行EXPLAIN,结果显示orders表type=ALL、rows=897421、Extra包含Using temporary; Using filesort,说明优化器未走created_at和status上的有效索引,需要进一步核对索引设计。
优化效果验证
问题根因是该表原有索引为(status, created_at),但查询条件中status是等值、created_at是范围,且ORDER BY列在联合索引中位置靠后,导致索引选择性下降。将索引调整为(created_at, status)并在测试环境用EXPLAIN ANALYZE验证后,orders表访问类型变为range,扫描行数降到约1300行,实际执行时间降至0.04秒。上线后实例CPU回落到40%以下,慢查询数恢复至个位数。聚搜云在整理这类RDS MySQL慢查询故障时也发现,当EXPLAIN的rows预估值与实际扫描值偏差过大时,先执行ANALYZE TABLE更新统计信息,往往比盲目建索引更有效。
- 点赞
- 收藏
- 关注作者
评论(0)