oracle统计信息的锁定与解锁
(一)问题背景
最近在对一个大约200万行数据的表查看执行计划时,发现存在异常,理论上应该返回100多万笔数据的,但是执行计划只返回了2条数据,比较奇怪,稍微思考,肯定是统计信息出问题了。
explain plan for select * from TABLE_***_NOTIFY where be_id is not null;
查看表的统计信息,发现最后一次收集统计信息是在2018年4月22日,已经是2年前的信息了,已经很久没有收集统计信息了
(二)Oracle什么情况下会自动收集统计信息
Oracle收集失效的统计信息的策略:自上次自动统计信息收集作业完成之后,如果DBA_TAB_MODIFICATIONS中记录的INSERT+UPDATE+DELETE所影响的行记录之和超过了DBA_TABLES中目标表记录数的10%,或者是自上次统计信息收集完成之后目标表执行过truncate操作,那么Oracle会认为目标表的统计信息已经失效,自动统计信息收集作业就会对目标表重新收集统计信息。
(三)Oracle为什么没有自动收集统计信息
根据上述策略,理论上肯定是要收集统计信息的,那么这里为什么没有收集统计信息呢?
首先想到的是统计信息被关闭了。根据个人经验,在某些公司高并发的业务系统中,统计信息的收集可能会引发异常等待事件,因此会把统计信息关闭,之后要么手动根据DBA_TAB_MODIFICATIONS编写脚本来收集,要么一直不收集,直到执行计划有问题再对单表收集。
那么是不是Oracle的自动统计信息收集功能关闭了呢?查询确认,发现自动统计信息是开启的。
SELECT WINDOW_NAME,AUTOTASK_STATUS,OPTIMIZER_STATS,SEGMENT_ADVISOR,SQL_TUNE_ADVISOR FROM DBA_AUTOTASK_WINDOW_CLIENTS ;
既然自动收集统计信息是开启的,那么只有可能是该表的统计信息被锁定了,可以尝试手动收集统计信息
SQL> exec dbms_stats.gather_table_stats(ownname => '***',tabname => '***',cascade => true);
发现有如下报错,可以确定是统计信息被锁了,由于过去很久,不知道之前是谁把统计信息给锁了,系统也多次换人接手,已经无从查起。
(四)解决办法
既然是统计信息锁了导致无法收集新的统计信息,那么接下来只要解锁并重新收集统计信息即可,方法如下:
--解锁某个表的统计信息 EXEC dbms_stats.unlock_table_stats(ownname => '***',tabname => '***'); --重新收集某个表的统计信息 EXEC dbms_stats.gather_table_stats(ownname => '***',tabname => '***',cascade => true);
还存在一个问题,数据库中可能还存在其他的表也被锁定了统计信息,我如何确认数据库中哪些表的统计信息被锁定:
SELECT owner,table_name,stattype_locked FROM DBA_TAB_STATISTICS a WHERE a.stattype_locked IN ('ALL','DATA','CACHE')
备注:stattype_locked为空代表统计信息未锁定。
【完】