某局点在使用 YashanDB 时,出现了 CPU 长时间 100% 的情况,业务受影响严重。经过分析发现,根源是某些 SQL 执行计划发生变化,背后竟是统计信息中的 analyze time 不一致惹的祸!

一、问题现象

系统负载飙升,数据库 CPU 占用持续 100%;

检查发现多个 SQL 性能异常,其中一个简单的“单行绑定 + 排序”语句变得非常慢;

执行计划发生变化,选用了性能较差的索引路径。

二、风险与影响

SQL 执行时间异常,影响正常业务响应;

操作系统负载升高,可能引发数据库或服务宕机;

计划选择错误,严重时可能导致全表扫描等高开销操作。

三、问题影响版本

经确认,该问题出现在 YashanDB 22.2.10.100 版本中。

image.png
四、问题根本原因分析

进一步分析后发现,问题的关键在于:

hist_head$ 表中列的analyze time早于 tab$ 表中的analyze time

这会导致优化器在调用 estColEqualOrNotParam 方法时:

尝试加载列统计信息;

由于 colStats = null,无法使用真实选择性;

系统自动使用默认 selectivity 值(0.04)进行估算;

实际上该列选择性极好,仅为 0.00003;

导致估算结果失真,从而选用了错误的索引。

示意图

image.png
五、处理方式与规避建议

在现网中,客户通过将错误索引设为 invisible,成功规避了错误执行计划。

推荐做法:

使用 alter index xxx invisible; 隐藏问题索引;

或者刷新列统计信息,确保 hist_head$ 与 tab$ 中时间一致;

日常维护中关注统计信息更新时间,避免残留旧数据干扰优化器判断。

六、问题排查与处理过程回顾

观察到 SQL 执行计划中,sub_account_id 的选择性非常低(实际数据分布极稀疏);

表数据量 6000 万,distinct 约 200 万,选择性应接近 0.00003;

但优化器使用默认 0.04.误判过滤效果,导致执行计划“跑偏”;

正确的执行计划 rows 估算值更接近实际数据分布,性能显著提升。

七、知识点补充

hist_head$:存放列的通用统计信息;

histgrm$:用于存放列的直方图数据(分布式信息);

优化器判断执行路径时优先参考这些表中的统计信息;

时间戳不一致,会导致优化器忽略某些信息,使用默认值。

八、总结建议

建议在收集统计信息时全表统一分析,避免局部更新留下时间戳差异;

运维过程中定期核查 tab$ 与 hist_head$ 中 analyze time 是否对齐;

如发现执行计划“突然变差”,可从统计信息完整性优先排查。


数据库砖家
1 声望0 粉丝