GaussDB 慢查询调优:一条 SQL 突然变慢,可能只是统计信息“过期”了

举报
yd_264409687 发表于 2026/11/05 15:03:26 2026/11/05
【摘要】 线上一条跑了半年的核心查询 SQL,某天开始响应时间从几十毫秒涨到了好几秒,业务侧开始零星超时。EXPLAIN 一看,执行计划跟之前完全不同——原本走索引扫描,现在变成了全表扫描。第一反应是索引失效或者数据量膨胀,但表结构没动,索引也在,数据量增长也在预期范围内。最后定位到的根因很朴素:统计信息过期了。一、统计信息为什么能让执行计划“翻脸”GaussDB 的优化器是基于代价的优化器(CBO)...

线上一条跑了半年的核心查询 SQL,某天开始响应时间从几十毫秒涨到了好几秒,业务侧开始零星超时。EXPLAIN 一看,执行计划跟之前完全不同——原本走索引扫描,现在变成了全表扫描。第一反应是索引失效或者数据量膨胀,但表结构没动,索引也在,数据量增长也在预期范围内。最后定位到的根因很朴素:统计信息过期了。

一、统计信息为什么能让执行计划“翻脸”

GaussDB 的优化器是基于代价的优化器(CBO) ,它靠统计信息(表的行数、列的 distinct 值数量、数据分布直方图等)来估算每种执行计划的代价,选最低代价的方案执行。统计信息不是实时更新的——它依赖 ANALYZE 触发采集,而自动采集有周期。如果表的写入模式发生了变化(比如某个状态字段的取值分布从均匀变成了极度倾斜),旧的统计信息会让优化器严重误判行数,进而选错 join 方式或扫描方式。

从经验数据看,约 10% 的性能问题根源是统计信息没有收集或已经陈旧。我们这次就是典型的“分布变化但统计没跟上”:某个业务状态字段上线新枚举值后,占比迅速增大,但列上的直方图还是旧分布,优化器仍按“该值极少”来估算,选择了 NestLoop,实际却要扫描大量行。

二、排查路径:先看计划,再对统计

定位慢 SQL 的正确顺序不是上来就加索引,而是先拿真实执行计划。EXPLAIN 只能看优化器的估算,真正要定位偏差,需要用 EXPLAIN ANALYZE 或 EXPLAIN PERFORMANCE 拿到实际执行的行数、耗时和内存,和估算值对比。我们对比后发现,某个扫描算子的 rows 估算值差了近两个数量级——这是统计信息失真的直接信号。

确认后,对相关表执行 ANALYZE 重新采集统计信息,再跑一次 EXPLAIN PERFORMANCE,执行计划回到了索引扫描,耗时恢复到毫秒级。

三、不能每次都靠手动 ANALYZE:建立统计信息治理习惯

手动 ANALYZE 解决单次问题,但要避免反复踩坑,需要把统计信息纳入日常治理:

1. 关注自动采集的覆盖范围。 GaussDB 的自动统计信息收集有默认策略,但对于写入频繁、分布容易倾斜的表,自动采集的频率可能不够。可以针对关键表配置更积极的 autovacuum / autoanalyze 参数,或者在业务低峰期通过调度任务手动触发 ANALYZE。

2. 用 SQL PATCH 做临时止血。 如果统计信息一时无法立刻更新,而线上业务等不起,可以用 SQL PATCH 对特定 SQL 绑定一个已知正确的执行计划,先稳住响应时间,再从容治理统计信息。这是“先止血、后治本”的实用手段。

3. 把“统计信息陈旧”加入慢 SQL 排查清单的第一页。 遇到执行计划突变、估算行数与实际严重不符时,优先检查统计信息的采集时间和数据分布,而不是盲目加索引或改 SQL。

四、总结

GaussDB 慢查询调优的完整链路是:看真实执行计划 → 对比估算与实际 → 检查统计信息 → 必要时 SQL PATCH 止血 → 建立定期 ANALYZE 机制。索引和 SQL 改写当然重要,但如果统计信息本身是错的,优化器再聪明也选不对路。这条 SQL 恢复之后,我们把核心表的统计信息采集频率纳入了巡检,之后再没出现过同类的“无故变慢”。

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。