暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

为啥表的统计信息没被及时自动收集?

B哥数据搬运工 2021-12-20
1140

背景:

       某周六早上,某应用在5点52分通过sqlloader进行导数,采用先truncate后load数,6点14分导完7千多万数据,而6点03分,数据库自动统计信息收集作业,收集到该表的数据量为0,期间刚好有联机交易进来,导致执行计划发生变化。而在导数后,程序尚未手工收集统计信息,最终导致故障发生。后面复盘时,发现在10点08分,数据库自动统计信息收集作业,又收集了一次该表的数据,这次的数据量是7千多万。详细案例复盘,可以参考我们内网“秘技阁”的数据库案例文章。

        到此,你可能会有疑问,周六、日,数据库的收集窗口很长,为啥6点14分已导完7千多万数据,等到10点08分才被数据库自动收集?延迟这么久?


先科普以下两点信息:

从oracle 11g开始,数据库默认的统计收集窗口为:

。周一至周五,每晚22点至第二天凌晨2点,共4小时

。周六、周日,从早上6点,持续20小时


表被自动收集统计信息的前提条件(自上次统计信息以来):

。表的inserts + deletes + updates超过表的总记录数的10%

。表被truncate过


        为了弄清楚根源问题,周六在测试环境模拟了一下场景:

1)使用CTAS方式,创建TMP_211218表, 表的数据量为74434,在16点左右,由于需要测试另一个功能,我对该表进行了truncate,后面又重新将dba_objects的数据插回TMP_211218表,最终数据量不变。 大家重点关注该表在18点之前的操作。


2)查看数据库自动统计信息收集的作业日志,大家可以看,从周六早上6点创建第1个作业后,每隔4个小时,数据库会自动1个作业,18点05分那个作业,运行了16秒就结束


3)在18点15分08秒时,对表TMP_211218进行truncate。从下图可以看到删除记录数及最后操作时间


至少,细心的朋友可能已经看出了问题了。

等待总是那么的煎熬,晚上我卡点又远程上去瞧了一下。

4)22点04分39秒,数据库尚未创建22点那个统计信息收集作业,dba_tab_modifitions还一直记录着下午18点15分08秒那次truncate。


5)再等了一分钟,再次查询,发现22点那个作业已经运行完毕,dba_tab_modifitions表已经没有记录了


6)查看表的统计信息,可以看到最后收集时间为22点05分


7)查看表的历史统计信息收集,该表不记录最后一次收集,从红框中看到收集时间是16点00分34秒,不在前面提到的常规收集每4个小时自动创建的统计信息收集作业窗口时间内。16点左右,我短暂调过收集参数,验证了功能后,又关掉了参数。看下图作业名为ORA$_ATSK_AUTOSMT,好几个都是在16点左右那几分钟


8)通过表的历史快照,也可以看到,18点15分08秒truncate表,删了7万多条记录,19、20、21、22这几次整点的快照,都录到了当时数据库变化情况,但没被自动收集,直到22点05分那次自动统计信息收集作业,才收集了该表的准确信息,隔了近4个小时


总结:

从上面的测试可以看到,虽然周六、日整个维护窗口有20个小时,每隔4个小时会创建一个收集作业,如果当前业务表满足了被自动收集的触发条件,但当前收集作业已结束,那么只能等下一个收集作业调起。因此,应用开发人员需要清楚了解自己的数据特点,在做大批量的导数或清数后,需要手工及时去收集统计信息,避免由于统计信息不准确,而影响了SQL的稳定性。不能太依赖于数据库本身的自动收集作业。

当然,在oracle 19c引入了high-frequency automatic optimizer statistics collection功能,可以解决以上问题,让收集的频率更短一些,但也存在一些缺陷,及频率的合理定义。请参考附录二:high-frequency automatic optimizer statistics collection





附录一:16点,重新插入记录截图


附录二:high-frequency automatic optimizer statistics collection



        

文章转载自B哥数据搬运工,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论