有两种方法,分别如下:方法一:
SYSDBA登录
exec dbms_scheduler.disable('SYS.GATHER_STATS_JOB');
exec dbms_scheduler.enable('SYS.GATHER_STATS_JOB');
方法二:
alter system set "_optimizer_autostats_job"=false scope=spfile;
alter system set "_optimizer_autostats_job"=true scope=spfile;
Pfile可以直接修改初始化参数文件然后重新启动数据库。
从Oracle Database 10g开始,Oracle在建库后就默认创建了一个名为GATHER_STATS_JOB的定时任务,用于自动收集CBO的统计信息。
这个自动任务默认情况下在工作日晚上10:00-6:00和周末全天开启。调用DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC收集统计信息。该过程首先检测统计信息缺失和陈旧的对象。然后确定优先级,再开始进行统计信息。
可以通过以下查询这个JOB的运行情况:
select * from Dba_Scheduler_Jobs where JOB_NAME ='GATHER_STATS_JOB'
其实同在10点运行的Job还有一个AUTO_SPACE_ADVISOR_JOB:
SQL> select JOB_NAME,LAST_START_DATE from dba_scheduler_jobs;
JOB_NAME LAST_START_DATE
------------------------------ ----------------------------------------
AUTO_SPACE_ADVISOR_JOB 04-DEC-07 10.00.00.692269 PM +08:00
GATHER_STATS_JOB 04-DEC-07 10.00.00.701152 PM +08:00
FGR$AUTOPURGE_JOB
PURGE_LOG 05-DEC-07 03.00.00.169059 AM PRC
然而这个自动化功能已经影响了很多系统的正常运行,晚上10点对于大部分生产系统也并非空闲时段。
而自动分析可能导致极为严重的闩锁竞争,进而可能导致数据库Hang或者Crash。
所以建议最好关闭这个自动统计信息收集功能:
exec DBMS_SCHEDULER.DISABLE('GATHER_STATS_JOB');
自动化永远而严重的隐患相伴随!
-----------------------------------------------------------------------------------------------------------------
Oracle 10g下cbo的自动统计分析功能很大程序的解决了因为9i下统计信息失效或者陈旧导致的sql语句选择了不合适的执行计划,该统计分析功能是通过dba_scheduler_jobs视图下的gather_stats_job来对系统的对象进行统计分析,gather_stats_job在星期一到星期五在晚上10点执行,双休从早上6点到星期一早上6点,该统计分析由于需要对数据库的所有对象进行分析,所以可能该job并没有完成,查看dba_scheduler_job_run_details可以对job执行是否完毕,可以看出在大型的生产库中很多情况该job都没有执行完毕就中止了。
SQL> select log_date,job_name,status from dba_scheduler_job_run_details where job_name='GATHER_STATS_JOB' order by log_id;
LOG_DATEJOB_NAME STATUS
-------------------------------------------------- -------------------- --------------------
07-4月 -12 06.01.40.434786 上午 +08:00GATHER_STATS_JOB STOPPED
09-4月 -12 10.27.13.012514 下午 +08:00GATHER_STATS_JOB STOPPED
10-4月 -12 10.33.26.498880 下午 +08:00GATHER_STATS_JOB STOPPED
11-4月 -12 10.08.14.335380 下午 +08:00GATHER_STATS_JOB STOPPED
12-4月 -12 10.24.57.878692 下午 +08:00GATHER_STATS_JOB STOPPED
13-4月 -12 10.09.23.672033 下午 +08:00GATHER_STATS_JOB STOPPED
14-4月 -12 06.01.43.666416 上午 +08:00GATHER_STATS_JOB STOPPED
那么gather_stats_job调用的是什么了,通过视图dba_scheduler_program可以查看
select program_action from dba_scheduler_programs where program_name='GATHER_STATS_PROG'
dbms_stats.gather_database_stats_job_proc
可以看出gather_stats_job调用dbms_stats.gather_database_stats_job_proc的procedure来检测统计信息缺失和失效的对象,然后确定优先级进行统计和分析信息。
(统计信息缺失可能都知道,但是失效如何解释,oracle中规定了修改的行达到了数据的10%,则就意味统计信息失效,关于这个修改的行则是oracle的另外一个视图sys.dba_tab_modification中的记录来对表等对象的统计信息是否失效来进行判断)
Cbo进行自动统计分析,不过如果查看生产系统中的表可以发现user_tables中的last_analyze_time不是近端时间的表大有所在,cbo进行自动统计分析需要表中的缺少统计信息,或者修改超过10%,如果没有达到,cbo下的自动分析并不会对该对象进行分析。
Cbo正是因为其根据统计信息而采取的最优的执行计划而减小了无谓的消耗,提高sql的性能,可以这么说cbo是完全依赖于统计信息,如果缺失cbo可以采取动态取样,oracle 10g下optimizer_dynamic_sampling默认是2,那么9i下的optimizer_dynamic_sampling是1。
(1) sql语句中必须有相应的至少一个没有采样信息的表
(2) 未分析的表没有索引
(3) 未分析的表占用的数据块要大于动态采样默认的数据块(32个)
9i下需要对表进行alter table tablename monitor 才会对表的修改进行监控,进而写入到dba_tab_monitoring视图中,而10g下默认都会对表进行监控。
这里说一下最近犯过的一个不知道算不算错误,生产库由于出现了大量的db file sequential read影响了性能,由于查看sql语句发现该逻辑读都很小,基本都是主键产生等待,根据awr的sga advisor增加了sga大小,然后重启数据库,居然发现了一个30多g的大表主键不停的fts,这可以说非常的不正常,隐式转换,统计信息失效但是由于设置的optimizer_dynamic_sampling觉得不是统计信息失效造成的,很有可能是隐式转换或者cbo的错误执行计划导致,由于没有metalink也无法去追踪具体的由来的,当时查看自动分析依然存在在晚上10点后会进行自动统计分析,第二天后业务恢复正常,选择了unique index。
不过当时自己其实完全可以利用dbms_stats.restore_table_stats(‘DESKTOP’,’ARTICLE’,sysdate-60/1440)恢复统计信息到一个小时前,不过案例不在,也是一个很痛苦的事情。
而统计信息保存的时间可以通过select dbms_stats.get_stats_hisory_retention from dual;
不过和undo_retention一样该参数并不是一个担保值
Select dbms_stats.get_stats_history_availability from dual;
统计信息的可用时间。
关闭cbo的自动统计分析dbms_scheduler.disable(‘GATHER_STATS_JOB’),cbo下的自动分析需要消耗一定量的latch可能造成latch竞争,不过合理的统计信息却是执行计划合理的保证,所以这里也没有什么关于是否开启于关闭自动统计分析的建议,不过如果能真正了解cbo具体的行为,那么根据你自己的业务情况,相信肯定有个合适的选择。