都19c年代了,有些数据库还是没有自动收集统计信息。
如何诊断?
先确认一下库里业务表的统计信息是否是新的:
-
-
COL OWNER FOR A20
-
COL TABLE_NAME FOR A30
-
COL LAST_ANALYZED FOR A20
-
SET LIN 200 PAGES 200
-
--19c
-
SELECT * FROM (select OWNER,t.TABLE_NAME,t.NUM_ROWS,t.BLOCKS,to_char(t.LAST_ANALYZED,'yyyy-mm-dd hh24:mi:ss')LAST_ANALYZED from dba_tables t where owner not in (SELECT USERNAME FROM DBA_USERS WHERE ORACLE_MAINTAINED='Y') and num_rows>100 and LAST_ANALYZED is not null ORDER BY LAST_ANALYZED DESC ) WHERE ROWNUM<101;
-
--11g num_rows为0说明可能被trunc
-
SELECT * FROM (select OWNER,t.TABLE_NAME,t.NUM_ROWS,t.BLOCKS,to_char(t.LAST_ANALYZED,'yyyy-mm-dd hh24:mi:ss')LAST_ANALYZED from dba_tables t where owner not in (SELECT USERNAME FROM DBA_USERS WHERE trunc(created)=(select trunc(created) from dba_users where username='SYS')) and num_rows>100 and LAST_ANALYZED is not null ORDER BY LAST_ANALYZED DESC ) WHERE ROWNUM<101;;
看看LAST_ANALYZED 列是否是最新日期,通常应该是昨天22:00,如果太旧说明没有更新。
统计信息收集是使用自动优化器统计信息收集维护任务实现的。任务的名称是“自动优化器统计集合”。该任务计划在维护窗口期间运行,并且应该收集有关具有过时或缺少统计信息的对象的统计信息。
自动收集统计信息受以下因素影响:
参数、任务、窗口、过程、表统计信息锁定属性、数据变化量、采样百分比、数据加载自动更新、imp导入元数据导致锁定、其他(最大进程数、最大游标数、os打开文件数、内存不足、空间不足等)
-
参数检查
-
col name for a32
-
col value for a10
-
select name,value from v$parameter where name in ('job_queue_processes','aq_tm_processes','statistics_level');
job_queue_processes 应该大于100
statistics_level 应该是 TYPICAL 或者 ALL
aq_tm_processes 应该是1
-
隐含参数 _optimizer_autostats_job
-
col name for a28
-
col descript for a42
-
select a.ksppinm name,b.ksppstvl value,a.ksppdesc descript
-
from x$ksppi a,x$ksppcv b where a.indx=b.indx and a.ksppinm like '%_optimizer_autostats_job%';
-
应该是 TRUE ,如果是 FALSE ,那么修改
alter system set "_optimizer_autostats_job"=true scope=spfile;
然后重启实例
-
基线维护作业状态
-
col owner for a8
-
col job_name for a25
-
col PROGRAM_NAME for a30
-
col STATE for a12
-
select owner,job_name,program_name,enabled,state from dba_scheduler_jobs where job_name='BSLN_MAINTAIN_STATS_JOB';
ENABLED列应该是TRUE,如果不是用以下方法
激活:
exec DBMS_SCHEDULER.enable('BSLN_MAINTAIN_STATS_JOB')
-
维护作业组状态
-
col group_name for a32
SELECT group_name, enabled FROM dba_scheduler_groups;
ENABLED列应该都是TRUE,如果不是的话,禁用、启用方法:
-
BEGIN
-
DBMS_SCHEDULER.disable(
-
name => 'SYS.MAINTENANCE_WINDOW_GROUP',
-
force => TRUE);
-
-
DBMS_SCHEDULER.enable(
-
name => 'SYS.MAINTENANCE_WINDOW_GROUP');
-
END;
-
/
-
自动任务窗口(非常重要)
-
-
col WINDOW_NEXT_TIME for a20
-
col window_name for a20
-
select window_name,to_char(window_next_time,'yyyy-mm-dd hh24:mi:ss')window_next_time,window_active,autotask_status,optimizer_stats,segment_advisor,sql_tune_advisor from DBA_AUTOTASK_WINDOW_CLIENTS;
-
如果AUTOTASK_STATUS
列不是ENABLED 那么需要执行exec DBMS_AUTO_TASK_ADMIN.enable。
-
exec dbms_auto_task_admin.enable (client_name => 'auto optimizer stats collection',operation => NULL,window_name => NULL)
如果OPTIMIZER_STATS 列不是ENABLED 那么需要执行:
-
BEGIN
-
dbms_auto_task_admin.disable(
-
client_name => 'auto optimizer stats collection',
-
operation => NULL,
-
window_name => NULL);
-
END;
-
/
这里的client_name 参数可以通过dba_autotask_client得到。
-
调度窗口
-
-
COL REPEAT_INTERVAL FOR A55
-
col NEXT_START_DATE for a22
-
col LAST_START_DATE for a22
-
col window_name for a20
-
col duration for a20
-
select window_name,repeat_interval,duration,to_char(next_start_date,'yyyy-mm-dd hh24:mi:ss')next_start_date,to_char(last_start_date,'yyyy-mm-dd hh24:mi:ss')last_start_date,enabled from DBA_SCHEDULER_WINDOWS where window_name not like 'WEEK%';
ENABLED列应该都是TRUE,并且平时22点开始4小时,周末6点开始20小时,如果不是,则修改:
-
--将周一窗口延长为6小时
-
BEGIN
-
dbms_scheduler.disable(
-
name => 'MONDAY_WINDOW');
-
dbms_scheduler.set_attribute(
-
name => 'MONDAY_WINDOW',
-
attribute => 'DURATION',
-
value => numtodsinterval(6, 'hour'));
-
dbms_scheduler.enable(
-
name => 'MONDAY_WINDOW');
-
END;
-
/
-
将周五的窗口改为23点开始,持续8小时
-
begin
-
dbms_scheduler.disable (NAME => '"SYS"."FRIDAY_WINDOW"', FORCE => TRUE);
-
-
dbms_scheduler.set_attribute (name => '"SYS"."FRIDAY_WINDOW"',attribute => 'repeat_interval',value=> 'freq=weekly;byday=fri;byhour=23;byminute=0;bysecond=0');
-
dbms_scheduler.set_attribute (name => '"SYS"."FRIDAY_WINDOW"',attribute => 'duration',value=> '0 08:00:00');
-
-
dbms_scheduler.enable (name => '"SYS"."FRIDAY_WINDOW"');
-
end;
-
/
-
控制不同的任务在不同的窗口执行
-
BEGIN
-
DBMS_AUTO_TASK_ADMIN.disable(
-
client_name => 'auto optimizer stats collection',
-
operation => NULL,
-
window_name => 'MONDAY_WINDOW');
-
-
DBMS_AUTO_TASK_ADMIN.disable(
-
client_name => 'auto space advisor',
-
operation => NULL,
-
window_name => 'MONDAY_WINDOW');
-
-
DBMS_AUTO_TASK_ADMIN.disable(
-
client_name => 'sql tuning advisor',
-
operation => NULL,
-
window_name => 'MONDAY_WINDOW');
-
END;
-
/
-
手工关闭或打开窗口
-
EXECUTE DBMS_SCHEDULER.CLOSE_WINDOW ('THURSDAY_WINDOW');
-
打开窗口
-
EXECUTE DBMS_SCHEDULER.OPEN_WINDOW ('MONDAY_WINDOW','');
检查自动任务执行历史
-
SELECT client_name,window_name,jobs_created,jobs_started,jobs_completed FROM dba_autotask_client_history WHERE client_name like '%stats%';
查看调度作业历史
-
set lin 200 pages 100
-
col owner for a4
-
col log_date for a20
-
col job_name for a23
-
col operation for a15
-
col status for a12
-
select *
-
from (select log_id,
-
to_char(log_date, 'yyyy-mm-dd hh24:mi:ss') log_date,
-
owner,
-
job_name,
-
operation,
-
status
-
from dba_scheduler_job_log
-
where job_name like 'ORA$AT_OS_OPT%'
-
order by log_id desc)
-
where rownum < 21
-
order by log_id;
看收集统计信息作业执行细节
-
col RUN_DURATION for a15
-
col job_name for a23
-
col error# for 99
-
col status for a10
-
col inst_id for 9
-
col ACTUAL_START_DATE for a20
-
col cpu_used for a16
-
select *
-
from (select log_id,
-
owner,
-
job_name,
-
status,
-
error#,
-
to_char(actual_start_date, 'yyyy-mm-dd hh24:mi:ss') actual_start_date,
-
run_duration,
-
instance_id inst_id,
-
cpu_used
-
from dba_scheduler_job_run_details
-
where job_name like 'ORA$AT_OS_OPT%'
-
order by log_id desc)
-
where rownum < 11
-
order by log_id;
看状态应该都是SUCCEEDED,执行时间不太长,没有错误。
如果这些维护作业或任务有问题了可以考虑重新初始化( 1945512.1)
-
重新初始化 maintenance jobs/tasks
-
@?/rdbms/admin/catmwin.sql
-
-
自动任务
-
col CLIENT_NAME for a32
-
select client_name , status from DBA_AUTOTASK_CLIENT order by 1;
至少第一个STATUS应该是ENABLED,如果是禁止的,则启用
-
-
BEGIN
-
DBMS_AUTO_TASK_ADMIN.enable(
-
client_name => 'auto optimizer stats collection',
-
operation => NULL,
-
window_name => NULL);
-
end;
-
/
下一个方向是统计信息本身
-
查表统计信息历史
-
select table_name,to_char(stats_update_time,'yyyy-mm-dd hh24:mi:ss') stats_update_time from dba_tab_stats_history where owner='SCOTT' and table_name='EMP';
-
可能没有,那就比较一下
-
set long 2000000
-
set pagesize 1000
-
-
select * from table(dbms_stats.diff_table_stats_in_history(
-
ownname => 'SCOTT',
-
tabname => 'EMP',
-
time1 => systimestamp,
-
time2 => to_timestamp('2022-02-27 17:47:19 PM','YYYY-MM-DD hh12:mi:ss AM'),
-
pctthreshold => 0));
-
看看历史记录
-
col savtime for a25
-
select to_char(savtime,'yyyy-mm-dd hh24:mi:ss') savtime, rowcnt, blkcnt, avgrln,samplesize
-
from WRI$_OPTSTAT_TAB_HISTORY
-
where obj#=(select object_id from dba_objects where owner='SCOTT' and object_name='EMP')order by 1;
-
检查对象当前统计信息
-
--表
-
col owner for a25
-
col last_analyzed for a25
-
select owner,table_name,num_rows,blocks,avg_space,avg_row_len,sample_size,to_char(LAST_ANALYZED,'yyyy-mm-dd hh24:mi:ss') last_analyzed from dba_tables where table_name='&TABLE_NAME' and owner='&owner';
-
-
--索引
-
select owner,table_name,index_name,blevel,leaf_blocks,distinct_keys,num_rows,sample_size,last_analyzed from dba_indexes where table_name='&TABLE_NAME' and owner='&owner';
-
-
--分区
-
select table_owner,table_name,partition_name,num_rows,blocks,avg_space,avg_row_len,sample_size,last_analyzed from dba_tab_partitions where table_name= '&TABLE_NAME' and owner='&OWNER';
-
-
--数据变化量
-
col TABLE_OWNER for a25
-
col PARTITION_NAME for a22
-
col SUBPARTITION_NAME for a22
-
alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
-
-
select * from (select * from dba_tab_modifications where table_owner='&OWNER' order by TIMESTAMP desc) where rownum<21;
-
-
--统计信息历史
-
col object_name for a25
-
col SUBOBJECT_NAME for a25
-
col OBJECT_TYPE for a15
-
SELECT ob.owner,ob.object_name,ob.subobject_name,
-
ob.object_type,obj#,
-
to_char(savtime,'yyyy-mm-dd hh24:mi:ss') savtime,
-
flags,rowcnt,
-
blkcnt,avgrln,samplesize,analyzetime,
-
cachedblk,cachehit,logicalread
-
FROM sys.WRI$_OPTSTAT_TAB_HISTORY, dba_objects ob
-
WHERE owner = upper('&OWNER')
-
and object_name = upper('&TABLE_NAME')
-
and object_type in ('TABLE')
-
and object_id = obj#;
-
-
抓取索引历史索引统计信息
-
select * from WRI$_OPTSTAT_IND_HISTORY where obj#=&OBJ_ID;
手工刷新,验证是否能够正常
exec dbms_stats.flush_database_monitoring_info
检查DBA_TAB_MODIFICATIONS 中是否有变化数据
检查表的统计信息是否锁定
select owner,table_name,stattype_locked from dba_tab_statistics
where table_name='%table_name';
如果关注的是非业务用户对象统计信息,那么如下逐个检查:
-
系统统计信息收集
-
exec dbms_stats.gather_system_stats
-
-
select * from sys.aux_stats$;
-
-
数据字典统计信息
-
exec DBMS_STATS.GATHER_DICTIONARY_STATS
-
-
select * from (
-
select table_name, last_analyzed from dba_tables where owner='SYS' order by last_analyzed, table_name) where rownum<21;
-
-
固定对象的
-
exec DBMS_STATS.GATHER_FIXED_OBJECTS_STATS
-
-
SELECT TABLE_NAME,LAST_ANALYZED
-
from DBA_TAB_STATISTICS
-
WHERE OWNER = 'SYS' AND TABLE_NAME LIKE 'X$%' ORDER BY LAST_ANALYZED ASC;
检查CJQ0、MMON进程的trc日志和数据库告警日志中22点是否有异常信息。
下一个方向是bug
-
ORA$AUTOTASK_CLEAN job执行'SYS.ORA$AGE_AUTOTASK_DATA'程序,底层调用dbms_autotask_prvt.age包清理了31天以前的KET$_CLIENT_TASKS
-
如果窗口和作业都正常,在22点后会自动填充DBA_AUTOTASK_TASK
-
-
-
窗口设置太短,可能导致dba_autotask_task为空 (DOC ID 1610257.1)
-
-
MMON 参与填充 DBA_AUTOTASK_CLIENT_JOB 和 DBA_AUTOTASK_TASK
-
如果mmon异常(例如ora-1000达到最大游标数)可能导致这两个视图空 (DOC ID 2097721.1)
-
-
如果task名有问题,例如数据库alert中出现如下报错:
-
ORA-12012: error on auto execute of job "SYS"."ORA$AT_OS_OPT_SY_936"
-
ORA-20001: Statistics Advisor: Invalid task name for the current user
-
ORA-06512: at "SYS.DBMS_STATS", line 47207
-
ORA-06512: at "SYS.DBMS_STATS_ADVISOR", line 882
-
ORA-06512: at "SYS.DBMS_STATS_INTERNAL", line 20059
-
ORA-06512: at "SYS.DBMS_STATS_INTERNAL", line 22201
-
ORA-06512: at "SYS.DBMS_STATS", line 47197
-
就需要考虑初始化相关对象 (DOC ID 2420581.1)
-
EXEC dbms_stats.init_package()
-
-
确认方法:
-
select name, ctime, how_created from sys.wri$_adv_tasks
-
where owner_name = 'SYS' and name in ('AUTO_STATS_ADVISOR_TASK','INDIVIDUAL_STATS_ADVISOR_TASK');
-
-
-
imp 时 rows=N先导入metadata,然后导入数据
-
If ROWS=n, then statistics for all imported tables will be locked after the import operation is finished.
-
-
-
参考:
-
新的 11g 默认作业(DOC ID 755838.1)
-
11g:调度程序维护任务或自动任务(DOC ID 1526120.1)
-
常见问题解答:自动收集统计信息(DOC ID 1233203.1)
-
DBA_AUTOTASK_CLIENT_JOB和DBA_AUTOTASK_TASK为空(DOC ID 2097721.1)
-
为什么自动统计信息收集可能显示为"卡住"且无法运行(DOC ID 1320246.1)
-
如何收集系统统计信息(DOC ID 149560.1)
-
以下不用执行
-
查看task状态(可能为空或与dba_autotask_client不一致)
-
col CLIENT_NAME for a32
-
col task_name for a25
-
SELECT client_name,task_name, status FROM dba_autotask_task;
-
自动收集任务与程序关联关系
-
-
col CLIENT_NAME for a32
-
col task_name for a25
-
col PROGRAM_ACTION for a42
-
col status for a10
-
select client_name, task_name, status, program_action
-
from dba_autotask_task, dba_scheduler_programs
-
where upper(task_name)=upper(program_name)
-
and client_name='auto optimizer stats collection';
应该是
如果没有,那么有可能是dba_autotask_task内容不正常。
阅读(2013) | 评论(0) | 转发(1) |