某局点在使用 YashanDB 时,出现了 CPU 长时间 100% 的情况,业务受影响严重。经过分析发现,根源是某些 SQL 执行计划发生变化,背后竟是统计信息中的 analyze time 不一致惹的祸!
一、问题现象
系统负载飙升,数据库 CPU 占用持续 100%;
检查发现多个 SQL 性能异常,其中一个简单的“单行绑定 + 排序”语句变得非常慢;
执行计划发生变化,选用了性能较差的索引路径。
二、风险与影响
SQL 执行时间异常,影响正常业务响应;
操作系统负载升高,可能引发数据库或服务宕机;
计划选择错误,严重时可能导致全表扫描等高开销操作。
三、问题影响版本
经确认,该问题出现在 YashanDB 22.2.10.100 版本中。
四、问题根本原因分析
进一步分析后发现,问题的关键在于:
hist_head$ 表中列的analyze time早于 tab$ 表中的analyze time
这会导致优化器在调用 estColEqualOrNotParam 方法时:
尝试加载列统计信息;
由于 colStats = null,无法使用真实选择性;
系统自动使用默认 selectivity 值(0.04)进行估算;
实际上该列选择性极好,仅为 0.00003;
导致估算结果失真,从而选用了错误的索引。
示意图
五、处理方式与规避建议
在现网中,客户通过将错误索引设为 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 是否对齐;
如发现执行计划“突然变差”,可从统计信息完整性优先排查。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。