oracle 11g 统计信息自动收集了解及时间调整实验


--问题:关于11g自动收集统计信息

--第一:什么时候收集 ?

--第二:用什么方法去收集?

--第三:收集所有对象 ?还是收集部分对象,怎么判断 ?

--第四:如果在最新收集统计信息之后出现查询性能问题 ?怎么恢复旧的统计信息 ?

--自动收集统计信息默认是开启的

--查看自动收集统计信息是否开启

SELECT CLIENT_NAME, STATUS FROM DBA_AUTOTASK_CLIENT;

SQL> SELECT CLIENT_NAME, STATUS FROM DBA_AUTOTASK_CLIENT;

CLIENT_NAME                                                  STATUS
------------------------------------------------------------ --------------------
auto optimizer stats collection                              ENABLED
auto space advisor                                           ENABLED
sql tuning advisor                                           ENABLED

SQL> col client_name for a40
SQL> col task_name for a20
SQL> col operation_name for a40
SQL> SELECT CLIENT_NAME,TASK_NAME,OPERATION_NAME,STATUS FROM dba_autotask_task;

CLIENT_NAME                              TASK_NAME            OPERATION_NAME                           STATUS
---------------------------------------- -------------------- ---------------------------------------- ------------------------
sql tuning advisor                       AUTO_SQL_TUNING_PROG automatic sql tuning task                ENABLED
auto optimizer stats collection          gather_stats_prog    auto optimizer stats job                 ENABLED

--查看具体操作

SELECT PROGRAM_NAME,PROGRAM_TYPE,PROGRAM_ACTION FROM dba_scheduler_programs  WHERE PROGRAM_NAME = 'GATHER_STATS_PROG';
SQL> col program_action for a80 
SQL> col program_type for a20
SQL> SELECT PROGRAM_NAME,PROGRAM_TYPE,PROGRAM_ACTION FROM dba_scheduler_programs  WHERE PROGRAM_NAME = 'GATHER_STATS_PROG';

PROGRAM_NAME                   PROGRAM_TYPE         PROGRAM_ACTION
------------------------------ -------------------- --------------------------------------------------------------------------------
GATHER_STATS_PROG              STORED_PROCEDURE     dbms_stats.gather_database_stats_job_proc

--查看具体什么时间做统计信息收集

SQL> SELECT a.WINDOW_NAME,a.REPEAT_INTERVAL,a.duration FROM dba_scheduler_windows a WHERE ENABLED = 'TRUE';

WINDOW_NAME                    REPEAT_INTERVAL                                                                  DURATION
------------------------------ -------------------------------------------------------------------------------- -------------------------------------------------------------------------------
MONDAY_WINDOW                  freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0                            +000 04:00:00
TUESDAY_WINDOW                 freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0                            +000 04:00:00
WEDNESDAY_WINDOW               freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0                            +000 04:00:00
THURSDAY_WINDOW                freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0                            +000 04:00:00
FRIDAY_WINDOW                  freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0                            +000 04:00:00
SATURDAY_WINDOW                freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0                             +000 20:00:00
SUNDAY_WINDOW                  freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0                             +000 20:00:00

7 rows selected

--可以看到,自动收集统计信息就是通过定时执行dbms_stats.gather_database_stats_job_proc来实现的。

--统计信息收集策略

--在Oracle 11g中,如果参数STATISTICS_LEVEL的值为TYPICAL(默认)或者ALL,

--则DBA_TAB_MODIFICATIONS会

--记录自上次自动统计信息收集完成之后对表insert、update、delete的操作影响行数以及是否truncate。

--策略:影响行数超过10%或者发生过truncate,那么就会收集该表的统计信息。

--查看历史执行情况

SELECT * FROM dba_autotask_client_history WHERE client_name LIKE '%stats%';

--禁用以及启用自动收集统计信息

--启用
BEGIN
  DBMS_AUTO_TASK_ADMIN.ENABLE(client_name => 'auto optimizer stats collection',
                              operation   => NULL,
                              window_name => NULL);
END;
--禁用
BEGIN
  DBMS_AUTO_TASK_ADMIN.DISABLE(client_name => 'auto optimizer stats collection',
                               operation   => NULL,
                               window_name => NULL);
END;

--关闭单个调度窗口
BEGIN
  DBMS_AUTO_TASK_ADMIN.disable(client_name => 'auto optimizer stats collection',
                               operation   => NULL,
                               window_name => 'MONDAY_WINDOW');
END;
/

--验证是否关闭
SELECT window_name, window_next_time, window_active, optimizer_stats
FROM dba_autotask_window_clients
WHERE window_name = 'MONDAY_WINDOW'
ORDER BY window_next_time;

SQL> SELECT window_name, window_next_time, window_active, optimizer_stats
  2  FROM dba_autotask_window_clients
  3  WHERE window_name = 'MONDAY_WINDOW'
  4  ORDER BY window_next_time;

WINDOW_NAME                    WINDOW_NEXT_TIME                                                                 WINDOW_ACTIVE OPTIMIZER_STATS
------------------------------ -------------------------------------------------------------------------------- ------------- ---------------
MONDAY_WINDOW                  13-DEC-21 10.00.00.000000 PM PRC                                                 FALSE         DISABLED

SQL> 
--关闭所有调度窗口
BEGIN
  DBMS_AUTO_TASK_ADMIN.disable (
    client_name   => 'auto optimizer stats collection',
    operation     => NULL,
    window_name   => NULL);
END;
/

--修改调度窗口的开始时间以及持续时间
--如下示例,将周一时间窗口时间到晚间20点30分

BEGIN
  DBMS_SCHEDULER.DISABLE(name => '"SYS"."MONDAY_WINDOW"', force => TRUE);
END;
/


BEGIN
  DBMS_SCHEDULER.SET_ATTRIBUTE(name       => '"SYS"."MONDAY_WINDOW"',
                 attribute  => 'REPEAT_INTERVAL',
                 VALUE      => 'FREQ=WEEKLY;BYDAY=MON;BYHOUR=20;BYMINUTE=30;BYSECOND=0');
END;
/


BEGIN
  DBMS_SCHEDULER.ENABLE(name => '"SYS"."MONDAY_WINDOW"');
END;
/

--验证修改
SELECT w.window_name, w.repeat_interval, w.duration, w.enabled
  FROM dba_autotask_window_clients c, dba_scheduler_windows w
 WHERE c.window_name = w.window_name
   AND c.optimizer_stats = 'ENABLED'
   AND c.window_name = 'MONDAY_WINDOW';

--如何恢复统计信息 

方法一:

--如何查看统计信息当前保留的天数
select dbms_stats.get_stats_history_retention from dual;
SQL> select dbms_stats.get_stats_history_retention from dual;

GET_STATS_HISTORY_RETENTION
---------------------------
                         31
            
--默认保留31天
--修改保留时间
execute dbms_stats.alter_stats_history_retention (xx);

--返回统计信息已经被删除到的日期(只有在这日期之后的统计信息才能被恢复)
select dbms_stats.get_stats_history_availability from dual;
GET_STATS_HISTORY_AVAILABILITY
---------------------------------------------------------------------------
05-NOV-21 10.16.00.242000000 PM +08:00

--知道可以恢复的时间之后
--执行恢复
execute dbms_stats.restore_table_stats('owner','table',date);
execute dbms_stats.restore_database_stats(date);
execute dbms_stats.restore_directory_stats(date);
execute dbms_stats.restore_fixed_objects_stats('owner',date);
execute dbms_stats.restore_system_stats(date);

select stale_stats,last_analyzed
from dba_tab_statistics
where owner = 'SCOTT'
and table_name = 'EMP';


SQL> select stale_stats,last_analyzed
  2  from dba_tab_statistics
  3  where owner = 'SCOTT'
  4  and table_name = 'DEPT';

STALE_STA LAST_ANALYZED
--------- ------------------
NO        22-JAN-21

exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SCOTT',tabname=>'DEPT',ESTIMATE_PERCENT=>10,method_opt=>'for all columns size 1',cascade=>true,force=>true,degree=>8);


SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SCOTT',tabname=>'DEPT',ESTIMATE_PERCENT=>10,method_opt=>'for all columns size 1',cascade=>true,force=>true,degree=>8);

PL/SQL procedure successfully completed.

SQL> select stale_stats,last_analyzed
  2  from dba_tab_statistics
  3  where owner = 'SCOTT'
  4  and table_name = 'DEPT';

STA LAST_ANALYZE
--- ------------
NO  08-DEC-21

execute dbms_stats.restore_table_stats('SCOTT','DEPT','05-NOV-21 10.16.00.242000000 PM +08:00');
ERROR at line 1:
ORA-20006: Unable to restore statistics , statistics history not available
ORA-06512: at "SYS.DBMS_STATS", line 28286
ORA-06512: at "SYS.DBMS_STATS", line 28305
ORA-06512: at line 1

execute dbms_stats.restore_table_stats('SCOTT','DEPT','07-DEC-21 10.16.00.242000000 PM +09:00');
SQL> execute dbms_stats.restore_table_stats('SCOTT','DEPT','07-DEC-21 10.16.00.242000000 PM +09:00');

PL/SQL procedure successfully completed.

SQL> select stale_stats,last_analyzed
  2  from dba_tab_statistics
  3  where owner = 'SCOTT'
  4  and table_name = 'DEPT';

STALE_STA LAST_ANALYZED
--------- ------------------
NO        22-JAN-21

--可以看到,表的统计信息又回到上次收集的时间点。

方法二:

--在收集某个表的统计信息,或者某个用户的统计信息或全库的统计信息之前,可以用下面的方法来导出和导入统计信息。
--创建统计信息历史保留表
exec  dbms_stats.create_stat_table(ownname=> 'SCOTT' ,stattab=> 'stat_table' ); 
--导出整个scheme的统计信息
exec  dbms_stats.export_schema_stats(ownname=>'SCOTT' ,stattab  => 'stat_table' ); 


--导入表的历史统计信息
exec  dbms_stats.import_table_stats(ownname=>'SCOTT',tabname=>'TEST',stattab=>'stat_table'); 

--如果进行分析后,大部分表的执行计划都走错,需要导回整个scheme的统计信息
exec  dbms_stats.import_schema_stats(ownname=>'SCOTT' ,stattab=>'stat_table' );

示例:
SQL> select stale_stats,last_analyzed
  2  from dba_tab_statistics
  3  where owner = 'SCOTT'
  4  and table_name = 'EMP';

STALE_STA LAST_ANALYZED
--------- ------------------
NO        22-JAN-21

SQL> exec  dbms_stats.create_stat_table(ownname=> 'SCOTT' ,stattab=> 'stat_table' );

PL/SQL procedure successfully completed.

SQL> exec  dbms_stats.export_schema_stats(ownname=>'SCOTT' ,stattab  => 'stat_table' );

PL/SQL procedure successfully completed.

SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'SCOTT',tabname=>'EMP',ESTIMATE_PERCENT=>10,method_opt=>'for all columns size 1',cascade=>true,force=>true,degree=>8);
PL/SQL procedure successfully completed.

SQL> select stale_stats,last_analyzed
  2  from dba_tab_statistics
  3  where owner = 'SCOTT'
  4  and table_name = 'EMP';

STALE_STA LAST_ANALYZED
--------- ------------------
NO        08-DEC-21

SQL> exec  dbms_stats.import_table_stats(ownname=>'SCOTT',tabname=>'EMP',stattab=>'stat_table');

PL/SQL procedure successfully completed.

SQL> select stale_stats,last_analyzed
  2  from dba_tab_statistics
  3  where owner = 'SCOTT'
  4  and table_name = 'EMP';

STALE_STA LAST_ANALYZED
--------- ------------------
NO        22-JAN-21

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM