执行计划基础(动态采样与统计信息收集)
统计信息
select window_name,window_next_time, autotask_status,optimizer_stats from DBA_AUTOTASK_WINDOW_CLIENTS;
select client_name,status from dba_autotask_client
where client_name='auto optimizer stats collection';
CLIENT_NAME STATUS
--------------------------------------------
auto optimizer stats collection ENABLED
/*
禁用这个任务的sql如下:(其实默认是有auto space advisor段指导、sql tuning advisor自动SQL优化和收集统计信息3个任务。
不过那2个基本没啥用,可以禁掉!):
*/
BEGIN
dbms_auto_task_admin.disable(client_name=>'auto optimizer stats collection',operation=>NULL,window_name=>NULL);
END;
--启用
begin
dbms_auto_task_admin.enable;
dbms_auto_task_admin.enable('auto optimizer stats collection', null,null);
end;
begin
dbms_auto_task_admin.enable('auto optimizer stats collection', null,'WEDNESDAY_WINDOW');
dbms_auto_task_admin.enable('auto optimizer stats collection', null,'FRIDAY_WINDOW');
dbms_auto_task_admin.enable('auto optimizer stats collection', null,'SATURDAY_WINDOW');
dbms_auto_task_admin.enable('auto optimizer stats collection', null,'THURSDAY_WINDOW');
dbms_auto_task_admin.enable('auto optimizer stats collection', null,'TUESDAY_WINDOW');
dbms_auto_task_admin.enable('auto optimizer stats collection', null,'SUNDAY_WINDOW');
dbms_auto_task_admin.enable('auto optimizer stats collection', null,'MONDAY_WINDOW');
end;
--配置维护窗口:
--可是使用DBMS_SCHEDULER 包来修改窗口属性。
--1:修改维护窗口
--先禁用维护窗口
BEGIN
dbms_scheduler.disable(
name => 'SATURDAY_WINDOW');
--修改维护窗口属性:
dbms_scheduler.set_attribute(
name => 'SATURDAY_WINDOW',
attribute => 'DURATION',
value => numtodsinterval(4, 'hour'));
--启用维护窗口
dbms_scheduler.enable(
name => 'SATURDAY_WINDOW');
END;
/
--对于当前打开的窗口,你需要首先禁用,然后修改再启用,配置立即生效,如果你不通过这三个过程来修改属性,属性是不会生效的,直到下一次窗口打开。
--2:创建新窗口:
BEGIN
dbms_scheduler.create_window(
window_name => 'EARLY_MORNING_WINDOW',
duration => numtodsinterval(1, 'hour'),
resource_plan => 'DEFAULT_MAINTENANCE_PLAN',
repeat_interval => 'FREQ=DAILY;BYHOUR=5;BYMINUTE=0;BYSECOND=0');
dbms_scheduler.add_window_group_member(
group_name => 'MAINTENANCE_WINDOW_GROUP',
window_list => 'EARLY_MORNING_WINDOW');
END;
/
--3:删除窗口:
BEGIN
DBMS_SCHEDULER.REMOVE_WINDOW_GROUP_MEMBER(
group_name => 'MAINTENANCE_WINDOW_GROUP',
window_list => 'EARLY_MORNING_WINDOW');
END;
/
--跟踪job运行情况:
--可以通过查询视图DBA_AUTOTASK_HISTORY追踪job运行情况:
select client_name,job_name,job_start_time
from dba_autotask_job_history where client_name='auto optimizer stats collection'
order by job_start_time desc;
动态采样
create table t_sample as select * from dba_objects;
Table created.
[email protected]>create index idx_t_sample_objid on t_sample(object_id);
Index created.
select num_rows, blocks, last_analyzed from user_tables where table_name = 'T_SAMPLE';
NUM_ROWS BLOCKS LAST_ANA
---------- ---------- --------
注释:表的统计信息创建后没有被收集
select index_name, num_rows, leaf_blocks, distinct_keys, last_analyzed from user_indexes where table_name = 'T_SAMPLE';
INDEX_NAME NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS LAST_ANA
------------------------------------------------------------ ---------- ----------- ------------- --------
IDX_T_SAMPLE_OBJID 86892 193 86892 11-06-20
注释:索引在创建的时候统计信息被收集。
set autotrace traceonly
select * from t_sample where object_id=20;
注释:以上表的统计信息没有被收集,所以用set autotrace traceonly 查看的时候走的是动态采样。
实验二:收集表的统计信息之后
exec dbms_stats.gather_table_stats(ownname => 'SYS',tabname => 'T_SAMPLE',estimate_percent => 10,method_opt=> 'for all indexed columns',cascade=>TRUE) ;
set autotrace off
select num_rows, blocks, last_analyzed from user_tables where table_name = 'T_SAMPLE';
NUM_ROWS BLOCKS LAST_ANA
---------------- ---------- --------
87720 1240 11-06-20
再次查看执行计划:
注:再次查看执行计划的时时候发现没有使用动态采样而是使用表的统计信息。
通过以上的实验可以得出以下的结论:
结论:
1. 统计信息默认情况下是每天晚上10点半后收集,如果新建对象还没来得级收集统计信息,就采用动态采样的方式。
2. 具体在set autotrace 跟踪的执行计划中,可以看到类似:- dynamic sampling used for this statement (level=2)
3. 除非你用类似/*+dynamic_sampling(t 0) */的HINT关闭这个动态采样。
4. 在收集过统计信息后,Oracle就不会采用动态采样。
注:建索引过程中,默认会收集索引相关的统计信息。