Oracle统计信息是优化器进行评估SQL的各种可能执行路径的Cost,从而指导优化器选择合适的执行计划。
一、Oracle的自动统计信息收集任务
Oracle每晚有自动任务对全库进行统计信息收集(默认周末是凌晨6点,持续20小时;工作日22点,最多持续4小时)
col WINDOW_NAME for a30;
col REPEAT_INTERVAL for a60;
col DURATION for a20;
set lines 400;
select t1.window_name,t1.repeat_interval,t1.duration,t1.ENABLED from dba_scheduler_windows t1,dba_scheduler_wingroup_members t2
where t1.window_name=t2.window_name and t2.window_group_name in ('MAINTENANCE_WINDOW_GROUP','BSLN_MAINTAIN_STATS_SCHED');
如果是周末为业务高峰的话,需要调整周六日的开始时间和持续时间:
begin
dbms_scheduler.set_attribute(name => 'SUNDAY_WINDOW', attribute => 'duration', value => '+000 10:00:00');
dbms_scheduler.set_attribute(name => 'SATURDAY_WINDOW', attribute => 'duration', value => '+000 10:00:00');
dbms_scheduler.set_attribute(name => 'SUNDAY_WINDOW', attribute => 'repeat_interval', value => 'Freq=daily;ByDay=SUN;ByHour=22;ByMinute=0;BySecond=0');
dbms_scheduler.set_attribute(name => 'SATURDAY_WINDOW', attribute => 'repeat_interval', value => 'Freq=daily;ByDay=SAT;ByHour=22;ByMinute=0;BySecond=0');
end;
关闭某一天的统计信息任务:
exec dbms_scheduler.disable( name => 'MONDAY_WINDOW',force => TRUE);
自动收集统计信息任务需要满足下面条件:
(1)statistics_level为TYPICAL或者ALL
(2)dba_autotask_client <auto optimizer stats collection> status值为ENABLED
select CLIENT_NAME,STATUS from dba_autotask_client;
可以使用如下语句关闭统计信息自动收集任务:
exec DBMS_AUTO_TASK_ADMIN.DISABLE(client_name => 'auto optimizer stats collection',operation => NULL,window_name => NULL);
重新开启:
exec DBMS_AUTO_TASK_ADMIN.ENABLE(client_name => 'auto optimizer stats collection',operation => NULL,window_name => NULL);
二、手动进行统计信息收集
分区级:
exec dbms_stats.gather_table_stats(ownname => 'MCCMV81',tabname => 'MCC_OUTPUT_EVENT',partname=>'P1',estimate_percent => '10') ;
表级:
exec dbms_stats.gather_table_stats(ownname => 'scott',tabname => 'work_list',estimate_percent => 1) ;
schema级:
exec dbms_stats.gather_schema_stats( ownname => 'CC',estimate_percent => 0.1, degree => 6 );
数据库级:
exec DBMS_STATS.GATHER_DATABASE_STATS(estimate_percent=>0.01,degree=>6);
索引级:
exec dbms_stats.gather_index_stats(ownname => 'cc',indname => 'IDX_ADM_PERMISSION_PID_MID',estimate_percent => '10',degree => '4') ;
使用 DBMS_STATS.GET_PREFS来得到默认的参数,常用的参数有:
select dbms_stats.get_prefs('CASCADE') from dual;
--DBMS_STATS.AUTO_CASCADE(oracle自己决定是否收集索引统计信息)
select dbms_stats.get_prefs('DEGREE') from dual;--NULL
select dbms_stats.get_prefs('ESTIMATE_PERCENT') from dual;--DBMS_STATS.AUTO_SAMPLE_SIZE(oracle自己决定采样率)
select dbms_stats.get_prefs('METHOD_OPT') from dual;--FOR ALL COLUMNS SIZE AUTO
select dbms_stats.get_prefs('NO_INVALIDATE') from dual;--DBMS_STATS.AUTO_INVALIDATE(oracle自己决定是否invalidate)
select dbms_stats.get_prefs('GRANULARITY') from dual;--AUTO(不收集subpartition,设为all会收集subpartition)
select dbms_stats.get_prefs('INCREMENTAL') from dual;--FALSE(不开启增量)
select dbms_stats.get_prefs('STALE_PERCENT') from dual;--10(表中被修改的行数超过stale_percent就认为表的统计数据过期,oracle自动将
STALE_STATS设为yes,下次任务会自动收集此表的统计信息;为no则不会收集)
参考文档:DBMS_STATS
使用DBMS_STATS.SET_GLOBAL_PREFS手动修改某些参数值:
exec dbms_stats.set_global_prefs('CASCADE','true');
恢复参数的默认值:
exec DBMS_STATS.RESET_GLOBAL_PREF_DEFAULTS;
三、其他
1、绑定/解绑表的统计信息
有时自动收集统计信息任务执行时某张表被truncate或者当时的统计信息不是通常值,导致执行计划错误,需要手动绑定这张表的统计信息
execute DBMS_STATS.LOCK_TABLE_STATS('CC','TEST');
select owner,table_name from dba_TAB_STATISTICS where stattype_locked='ALL' ;
execute DBMS_STATS.UNLOCK_TABLE_STATS('CC','TEST');
2、查询表的历史统计信息
查看某张表/索引统计信息收集的历史:
SELECT ob.owner, ob.object_name, ob.object_type, rowcnt,BLKCNT, avgrln ,samplesize, analyzetime FROM sys.WRI$_OPTSTAT_TAB_HISTORY, dba_objects ob WHERE owner='CC' and object_name='TEST' and object_id=obj# order by savtime asc;
SELECT ob.owner, ob.object_name, ob.object_type, rowcnt,BLKCNT,samplesize, analyzetime FROM sys.WRI$_OPTSTAT_IND_HISTORY, dba_objects ob WHERE owner='CC' and object_name='TXN_VRTCL_LS_HIST_PK';
3、恢复表在某历史时刻的统计信息
exec dbms_stats.restore_table_stats('API_DATA', 'MS_EDM_EVENTS', TO_DATE('29-Jun-2015 11:00', 'DD-MON-YYYY HH24:MI'));
4、查看统计信息最长的保留时间:This function returns oldest timestamp wherestatistics history is available
select DBMS_STATS.GET_STATS_HISTORY_AVAILABILITY from dual;