【问题分类】 性能优化
【关键词】 统计信息失效、STALE_STATS、执行计划偏差
问题现象
在使用 YashanDB 时,当表中数据量发生一定变化后,虽然没有显式更新统计信息,但查询的执行计划却突然变“笨”了,查询效率明显下降。
例如如下案例操作:
-- 创建测试表
create table t1 (id int, name varchar2(200));
create index t1_id_ind on t1(id);
create index t1_name_ind on t1(name);
-- 初始插入100行
begin
for i in 1..100 loop
insert into t1 values(i,'aaaa'||i);
end loop;
commit;
end;
-- 收集统计信息
begin
DBMS_STATS.GATHER_TABLE_STATS('SYS', 'T1', '',1, FALSE, 'FOR ALL COLUMNS SIZE AUTO', 4, 'AUTO', TRUE);
end;
-- 查询统计信息状态
SELECT OWNER, TABLE_NAME, LAST_ANALYZED, NUM_ROWS, STALE_STATS FROM dba_tab_statistics WHERE table_name = 'T1';
-- 设置失效比例为 0.1(默认是10%)
exec DBMS_STATS.SET_TABLE_PREFS('SYS', 'T1', 'STALE_PERCENT', '0.1');
-- 增加21行数据(超过0.1阈值)
begin
for i in 101..121 loop
insert into t1 values(i,'aaaa'||i);
end loop;
commit;
end;
此时再执行查询计划:
explain SELECT * FROM T1 WHERE ID IN (1,2) ORDER BY NAME DESC;
你可能会发现——查询效率变差了!为什么?
问题原因解析
这是因为 YashanDB 的统计信息触发“失效机制”生效了:
当新增/修改/删除的数据量超过设定的失效比例(默认10%,此处我们设置为0.1即10%),数据库会标记该表的统计信息为“已失效”,导致优化器无法基于准确的统计信息生成执行计划。
解决/规避方案
为避免查询计划偏差,可以从以下几方面入手:
1.定时统一收集统计信息
建议在业务低峰时段统一执行 DBMS_STATS.GATHER_TABLE_STATS,确保最新数据能同步到优化器中。
2.修改失效比例参数
将表的 STALE_PERCENT 设置为 0.表示数据变动不再触发统计信息失效机制:
exec DBMS_STATS.SET_TABLE_PREFS('SYS', 'T1', 'STALE_PERCENT', '0');
3.锁定统计信息
对于更新频率较低的表,也可以选择锁定其统计信息,避免被意外刷新:
exec DBMS_STATS.LOCK_TABLE_STATS('SYS', 'T1');
4.降低收集负担:调整统计等级参数
将 statistics_level 设置为 BASIC 可关闭部分自动统计收集开销(需谨慎使用):
alter system set statistics_level = BASIC;
影响范围与修复版本
影响版本:适用于所有 YashanDB 版本
修复版本:该设计为预期行为,无需修复,建议按上方方法规避
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。