ORACLE10g自動收集CBO統計信息Oracle

從Oracle Database 10g開始,Oracle在建庫後就默認創建了一個名爲GATHER_STATS_JOB的定時任務,用於自動收集CBO的統計信息。

這個特性減少了由於sql語句統計失效或陳舊而導致性能很差的可能性,通過提高查詢優化器的最佳的輸出提高sql執行的性能.
gather_stats_job
默認的,在數據庫創建的時候就創建了gather_stats_job,執行dbms_stats.gather_database_stats_job_proc過程,使用schedular.
默認的定義了兩個窗口.
weekenight_window定義在下午10點到上午六點.從週一到週五.
weekend_window定義從上午12點到週一12點.

調用DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC收集統計信息。
該過程首先檢測統計信息缺失和陳舊的對象。然後確定優先級,再開始進行統計信息。

說明:當做完統計信息後,如果對對象的行數修改達到10%,DBMS_STATS就認爲是統計信息過舊。

可以通過以下查詢這個JOB的運行情況:
SQL> select * from Dba_Scheduler_Jobs where JOB_NAME ='GATHER_STATS_JOB'

其實同在10點運行的Job還有一個AUTO_SPACE_ADVISOR_JOB:

SQL> select JOB_NAME,LAST_START_DATE from dba_scheduler_jobs;

JOB_NAME LAST_START_DATE
------------------- ----------------------------------------
AUTO_SPACE_ADVISOR_JOB 04-DEC-07 10.00.00.692269 PM +08:00
GATHER_STATS_JOB 04-DEC-07 10.00.00.701152 PM +08:00
FGR$AUTOPURGE_JOB
PURGE_LOG 05-DEC-07 03.00.00.169059 AM PRC

默認的maintenance_window_group組包含這兩個窗口.
gather_stats_job使用特定的計劃任務叫auto_tasks_job_class.這個類是自動創建的,而且跟特定的資源組聯繫,這個組叫做auto_task_consumer_group.這樣確保任務使用auto_task_consumer_group.如果想控制gather_stats_job的資源使用,之需要爲maintenance_window_group定義一個資源管理者組來爲auto_task_cousumer_group分配資源.
爲了讓gather_stats_job工作正常,必須確定statistics_level初始化參數設置爲typical.
改變gather_stats_job的計劃任務
可以爲定義的管理窗口來自定義開放時間.例如,可以改變他們的時間間隔和重複的頻度.也可以添加資源計劃到這些窗口中,來控制gather_stats_job使用的資源.
從db control主頁,點擊管理標籤,然後在scheduler部分點擊windows鏈接.就讓到了scheduler windows頁.這裏可以選中一個窗口,並且可以點edit來修改它的特性.在這頁,還可以打開或關閉特定的窗口.只要在下拉框爲特定的窗口選擇相應的行爲,點ok.
鎖定統計
阻止自動收集
主要用在可變的表中
-沒有統計的鎖定,意味着動態的取樣.
-鎖定代表值的統計
在oracle10g,可以看到特定表的統計,通過新的dbms_stats包的lock_table_stats過程.可以鎖定一個表的統計,來阻止自動統計收集,這樣就可以使用動態的取樣.也可以在某個時間點鎖定可變的表的統計.
可以使用lock_schema_stats運行在sechma基本鎖定統計.
可以查看user/all/dba_tab_statistics視圖來看stattype_locked列來看一個表是不是被鎖定.


然而這個自動化功能已經影響了很多系統的正常運行,晚上10點對於大部分生產系統也並非空閒時段。
而自動分析可能導致極爲嚴重的閂鎖競爭,進而可能導致數據庫Hang或者Crash。

所以建議最好關閉這個自動統計信息收集功能:
exec DBMS_SCHEDULER.DISABLE('GATHER_STATS_JOB');

自動化永遠而嚴重的隱患相伴隨!

對於易變對象的變化,可以人工收集統計信息(DBMS_STATS)外 主要兩種處理方式:

一種就是刪除統計信息。使它的統計信息爲空,對於任何統計信息缺失的表,oracle會用動態取樣特性自動產生統計信息。如果使用久的統計信息 就可能產生錯誤的執行計劃。
需要設置optimizer_dynamic_sampling爲2(ORACLE10G默認值)或以上都可以啓動此特性。

optimizer_dynamic_sampling ,提供在SQL分析的時候,自動根據不同的Level(0-10)以不同的準確度分析SQL中未被analyze過的表,意在爲CBO提供更多的統計信 息。在Oracle9iR2中引入,默認爲Level 1,10g默認爲2 。

http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96536/ch1135.htm#REFRN10140

Level 0: Do not dynamically sample the table(s)

Level 1:Sample tables that have not been analyzed if there is more than one table in the query,the table in question has not been analyzed and it has no indexes,and the optimizer determines that the query plan would be affected based on the size of this objects

Level 2:Sample all unanalyzed tables referenced in the query using default sampling amounts(small sample)

Level 3 -- Level 10 ........更詳細的sample。

例如:dbms_stats.delete_table_stats('table_name' ,'VOLATILE_TABLE')

另一種就是設置爲表進行鎖定,這樣就可以不更新統計信息(注意LOCK表以後,表就不能修改了)。

dbms_stats.lock_table_stats('table_name' ,'VOLATILE_TABLE');

http://hi.baidu.com/dbatao/blog/item/f3effdae2791cccb7dd92a4a.html

Metalink 上的解釋:

Subject: How to check what automatic statistics collection is scheduled on 10g
Doc ID: Note:377143.1 Type: BULLETIN
Last Revision Date: 16-FEB-2007 Status: PUBLISHED
This article is being delivered in Draft form. and may contain errors.
Please use the MetaLink "Feedback" button to advise Oracle of any issues related to this article.
PURPOSE
This Note provides information on the How to check what automatic statistics collection is scheduled on 10g
{
SCOPE AND APPLICATION
ME;S+a [4M289604Users collecting statistics on database objects for use by the Cost Based Optimizer (CBO)

How to check what automatic statistics collection is scheduled on 10g
With Oracle 10g, the gathering of statistics has become automated.
The GATHER_STATS_JOB that is built in the database creation process schedules automatic statistics collection.
The job initiates a 'program' of statistics gathering appropriate for the database in question.
j289604The job details can be viewed by querying the DBA_SCHEDULER_JOBS view:
select job_name, job_type, program_name, schedule_name, job_class
from dba_scheduler_jobs
where job_name = 'GATHER_STATS_JOB';
JOB_NAME JOB_TYPE PROGRAM_NAME SCHEDULE_NAME JOB_CLASS
------------------------------ ---------------- ------------------- ------------------------- ------------------------------
GATHER_STATS_JOB GATHER_STATS_PROG MAINTENANCE_WINDOW_GROUP AUTO_TASKS_JOB_CLASS

The output shows that the 'GATHER_STATS_JOB' schedules a program 'GATHER_STATS_PROG' in the 'MAINTENANCE_WINDOW_GROUP' time schedule.
The PROGRAM_NAME 'GATHER_STATS_PROG' starts the DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC stored procedure: select PROGRAM_ACTION
from dba_scheduler_programs
where PROGRAM_NAME = 'GATHER_STATS_PROG';
PROGRAM_ACTION
dbms_stats.gather_database_stats_job_proc

The job is scheduled according to the value of the SCHEDULE_NAME field.
this example, the schedule being used is: 'MAINTENANCE_WINDOW_GROUP'.
This schedule is defined in the DBA_SCHEDULER_WINGROUP_MEMBERS view:
select *
from DBA_SCHEDULER_WINGROUP_MEMBERS
where WINDOW_GROUP_NAME = 'MAINTENANCE_WINDOW_GROUP';

WINDOW_GROUP_NAME WINDOW_NAME
------------------------- ------------------------------
MAINTENANCE_WINDOW_GROUP WEEKNIGHT_WINDOW MAINTENANCE_WINDOW_GROUP WEEKEND_WINDOW
The meaning of these 'windows' can be found in 'DBA_SCHEDULER_WINDOWS':
select window_name, repeat_interval, duration
from dba_scheduler_windows
where window_name in ('WEEKNIGHT_WINDOW', 'WEEKEND_WINDOW')

WINDOW_NAME REPEAT_INTERVAL DURATION
----------------- ------------------------------------------------------------- ------------- WEEKNIGHT_WINDOW freq=daily;byday=MON,TUE,WED,THU,FRI;byhour=22;byminute=0; bysecond=0 +000 08:00:00
WEEKEND_WINDOW freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0 +002 00:00:00
The meaning of these entries is as follows
The WEEKNIGHT_WINDOW is scheduled each week day at 10PM. and should last a maximum of 8 hours.
The WEEKEND_WINDOW is scheduled each Saturday at 0AM and should last 2 days max
If the START_DATE and END_DATE columns (Not shown) are NULL, then this job will run continuously.
All these definitions can be found in the $ORACLE_HOME/rdbms/admin/catmwin.sql script.

Oracle 10g 版本最後不再支持(而不是反對)基於規則的優化器 (RBO)。因爲 CBO 依靠準確的(或者說比較準確的)統計信息來產生優化的執行路徑,所以 DBA 需要確保定期收集統計信息,創建另一個執行覈對清單。在 10g 之前,這一過程可能由於多種原因而徒勞無功。在 10g 中已經消除了很多這類的顧慮,它能夠自動收集統計信息。在 Oracle9i 中,您可以通過打開表監視選項 (ALTER TABLE ...MONITORING) 然後檢查這些表的視圖 DBA_TAB_MODIFICATIONS,檢查表中的數據是否已明顯更改過。

在 10g 中,已不再使用 MONITORING 語句了。而通過設置初始化參數 STATISTIC_LEVEL 爲 TYPICAL 或 ALL,就可以自動收集統計信息。(默認值爲 TYPICAL,因此可以隨即啓用自動收集統計信息的功能。)Oracle 數據庫 10g 具有一個預定義的調度程序作業,名稱爲 GATHER_STATS_JOB,它由 STATISTIC_LEVEL 參數的適當數值所激活。

SQL> show parameter statistics_

NAME TYPE VALUE
------------------------------------ ----------- -----------------
statistics_level string TYPICAL

statistics_level 默認是typical,在10g中表監控是激活的,強烈建議在10g中此參數的值是typical。如果STATISTICS_LEVEL設置爲basic,不僅不能監控表,而且將禁掉如下一些10g的新功能:
ASH(Active Session History)
ASSM(Automatic Shared Memory Management)
AWR(Automatic Workload Repository)
ADDM(Automatic Database Diagnostic Monitor)

統計信息的收集是資源相當密集的工作,因此您可能希望確保它不影響數據庫的正常操作。在 10g 中,您可以使這一工作自動完成:可對一個名爲 AUTO_TASK_CONSUMER_GROUP 的特定資源用戶組進行預定義,用於自動執行一些任務,比如收集統計信息。該用戶組確保這些統計信息收集作業的優先權低於默認用戶組,因此減少或消除了自動化任務佔用整個機器的風險。

這個自動任務默認情況下在工作日晚上10:00 - 6:00 和週末全天開啓。調用 DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC 收集統計信息。該過程首先檢測統計信息缺失和陳舊的對象。然後確定優先級,再開始進行統計信息。

可以通過以下查詢這個JOB的運行情況:

SQL> set lines 256
SQL> col last_start_date format a40
SQL> col last_run_duration format a30
SQL> SELECT owner, enabled, auto_drop, restartable, state, run_count, failure_count, last_start_date, last_run_duration FROM dba_scheduler_jobs where job_name = 'GATHER_STATS_JOB';

OWNER ENABL AUTO_ RESTA STATE RUN_COUNT FAILURE_COUNT LAST_START_DATE LAST_RUN_DURATION
------------------------------ ----- ----- ----- --------------- ---------- ------------- ---------------------------------------- ------------------------------
SYS TRUE FALSE TRUE SCHEDULED 57 0 27-NOV-08 10.00.02.228110 PM +08:00 +000000000 00:00:25.870394
如果希望將參數 STATISTIC_LEVEL 設爲 TYPICAL 卻不希望自動收集統計信息時該怎麼辦?很簡單。只需使用以下語句來禁用調度程序作業即可:

SQL> exec DBMS_SCHEDULER.DISABLE('GATHER_STATS_JOB');

那麼您爲什麼要這樣做呢?有很多原因 — 其中一個原因是,雖然表中大部分行發生了變化,但分佈情況可能沒有改變,這在數據倉庫中很常見。在這種情況下,您不希望再次收集統計信息,而只是希望重用原來的統計信息。另一個原因可能是您正在使用分區交換功能來刷新物化視圖 (MV),並且不希望收集關於物化視圖的統計信息,因爲關於被交換表的統計信息也會被導入。但是,您也可以將特定的表排除在自動統計信息收集作業之外,而不需要禁止整個作業。

在優化器收集統計信息時可能出現的複雜情況之一是執行計劃的改變 — 也就是說,原來的優化方法在收集統計信息之前一直工作良好,但是在此之後,由於新收集的統計信息產生了不良計劃,導致查詢突然出錯。這種問題並不少見。

爲避免這種災難,統計信息的收集作業在收集新信息之前保存當前的統計信息。如果出現問題,您總可以返回到原有的統計信息,或者至少可以檢查二者之間的不同之處,以便於解決問題。

例如,假設在 5 月 31 日晚上 10:00 開始運行表 REVENUE 上的統計信息收集作業,而隨後查詢的性能變差。Oracle 保存了原有的統計信息,您可以通過執行以下命令重新獲取這些信息:

SQL> exec dbms_stats.restore_table_stats ( 'ARUP', 'REVENUE', '31-MAY-04 10.00.00.000000000 PM -04:00');

此命令恢復到 5 月 31 日晚上 10:00 爲止的統計信息,時間信息是以 TIMESTAMP 數據類型提供。這樣您就立即還原了由新的統計信息收集程序所作的更改。

您能夠恢復的時間長度是由保留參數所決定的。要查看當前的保留參數,可使用以下查詢:

SQL> select DBMS_STATS.GET_STATS_HISTORY_RETENTION from dual;

GET_STATS_HISTORY_RETENTION
---------------------------
31

在本示例中表示可以保存相當於 31 天的統計信息,但並不能予以保證。要了解統計信息所覆蓋到的確切時間和日期,只需使用以下查詢:

SQL> select DBMS_STATS.GET_STATS_HISTORY_AVAILABILITY from dual;

GET_STATS_HISTORY_AVAILABILITY
----------------------------------------------------------------
27-10月-08 11.14.20.357622000 下午 +08:00

該查詢表明可用的最陳舊統計信息日期爲 10 月 27 日下午 11:14。

您可以通過執行內建的函數將保留時間設爲不同的值。例如,要將其設爲 45 天,可使用:

SQL> exec DBMS_STATS.ALTER_STATS_HISTORY_RETENTION (45);

另外爲什麼有部分表沒有被分析呢, 原因跟表DBA_TAB_MODIFICATIONS有關.

Oracle? Database Performance Tuning Guide
10g Release 2 (10.2)
Part Number B14211-01
14.3.1.5 Determining Stale Statistics

Statistics must be regularly gathered on database objects as those database objects are modified over time. In order to determine whether or not a given database object needs new database statistics, Oracle provides a table monitoring facility. This monitoring is enabled by default when STATISTICS_LEVEL is set to TYPICAL or ALL. Monitoring tracks the approximate number of INSERTs, UPDATEs, and DELETEs for that table, as well as whether the table has been truncated, since the last time statistics were gathered. The information about changes of tables can be viewed in the USER_TAB_MODIFICATIONS view. Following a data-modification, there may be a few minutes delay while Oracle propagates the information to this view. Use the DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO procedure to immediately reflect the outstanding monitored information kept in the memory.

The GATHER_DATABASE_STATS or GATHER_SCHEMA_STATS procedures gather new statistics for tables with stale statistics when the OPTIONS parameter is set to GATHER STALE or GATHER AUTO. If a monitored table has been modified more than 10%, then these statistics are considered stale and gathered again.

默認情況下Oracle會記錄數據庫表的變化, 只有變化超過10%的表,纔會做自動分析
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章