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