優化器統計範圍:html
表統計; --行數,塊數,行平均長度;all_tables:NUM_ROWS,BLOCKS,AVG_ROW_LEN;
列統計; --列中惟一值的數量(NDV),NULL值的數量,數據分佈;
--DBA_TAB_COLUMNS:NUM_DISTINCT,NUM_NULLS,HISTOGRAM;
索引統計;--葉塊數量,等級,聚簇因子;
--DBA_INDEXES:LEAF_BLOCKS,CLUSTERING_FACTOR,BLEVEL;
系通通計;--I/O性能與使用率;
--CPU性能與使用率;
--存儲在aux_stats$中,須要使用dbms_stats收集,I/O統計在X$KCFIO中;ios
-------------
analyze
-------------
須要使用ANALYZE統計的統計:
使用LIST CHAINED ROWS和VALIDATE子句;
收集空閒列表塊的統計;
Analyze table tablename compute statistics;
Analyze index|cluster indexname estimate statistics;
ANALYZE TABLE tablename COMPUTE STATISTICS
FOR TABLE
FOR ALL [LOCAL] INDEXES
FOR ALL [INDEXED] COLUMNS;
ANALYZE TABLE tablename DELETE STATISTICS
ANALYZE TABLE tablename VALIDATE REF UPDATE
ANALYZE TABLE tablename VALIDATE STRUCTURE [CASCADE]|[INTO TableName]
ANALYZE TABLE tablename LIST CHAINED ROWS [INTO TableName]
ANALYZE 不適合作分區表的分析
----------------------
dbms_stats
----------------------
dbms_stats能良好地估計統計數據(尤爲是針對較大的分區表),並能得到更好的統計結果,最終制定出速度更快的SQL執行計劃。
這個包的下面四個存儲過程分別收集index、table、schema、database的統計信息:
dbms_stats.gather_table_stats 收集表、列和索引的統計信息;
dbms_stats.gather_schema_stats 收集SCHEMA下全部對象的統計信息;
dbms_stats.gather_index_stats 收集索引的統計信息;
dbms_stats.gather_system_stats 收集系通通計信息
dbms_stats.GATHER_DICTIONARY_STATS: 全部字典對象的統計;
DBMS_STATS.GATHER_DICTIONARY_STATS 其收集全部系統模式的統計sql
dbms_stats.delete_table_stats 刪除表的統計信息
dbms_stats.delete_index_stats 刪除索引的統計信息
dbms_stats.export_table_stats 輸出表的統計信息
dbms_stats.create_state_table
dbms_stats.set_table_stats 設置表的統計
dbms_stats.auto_sample_size數據庫
統計收集的權限
==========================
必須授予普通用戶權限
sys@ORADB> grant execute_catalog_role to hr;
sys@ORADB> grant connect,resource,analyze any to hr;windows
統計收集的時間考慮
==========================
當參數STATISTICS_LEVEL設置爲TYPICAL或者ALL,系統會在夜間自動收集統計信息。
查看系統自動收集統計信息的job:
SELECT * FROM dba_scheduler_jobs WHERE job_name = 'GATHER_STATS_JOB';
也能夠disable自動收集統計信息:
BEGIN
dbms_scheduler.disable('GATHER_STATS_JOB');
END;服務器
使用手工統計架構
對全部更改活動中等的對象自動統計應該足夠充分,因爲自動統計收集在夜間進行,所以對於一些更新頻繁的對象其統計可能已通過期。兩種典型的對象:
高度變化的表在白天的活動期間被TRUNCATE/DROP並重建;
塊加載超過自己總大小10%的對象;oracle
對於第一種對象可使用如下兩種方法:
1 將這些表上的統計設置爲NULL,當Oracle遇到沒有統計的表時,將動態收集必要的統計做爲查詢優化的一部分;
動態收集特徵由OPTIMIZER_DYNAMIC_SAMPLING控制,這個參數應該設置爲大於等於2,默認爲2。能夠經過刪除並鎖住統計將統計設置爲NULL:
DBMS_STATS.DELETE_TABLE_STATS('SCHEMA','TABLE');
DBMS_STATS.LOCK_TABLE_STATS('SCHEMA','TABLE');less
2 將這些表上的統計設置爲表明表典型狀態的值。在表具備某個有表明性的值時收集統計,而後鎖住統計;
因爲夜間收集的統計未必適合於白天的負載,所以這些狀況下使用手工收集比GATHER_STATS_JOB更有效。
對於塊加載,統計應該在加載後馬上收集,一般合併在加載語句的後面防止遺忘。
對於外部表,統計不能經過GATHER_DATABASE_STATS,GATHER_SCHEMA_STATS以及自動統計收集收集。所以須要使用GATHER_TABLE_STATS在單個表上收集統計,而且在外部表上不支持取樣,ESTIMATE_PERCENT應該被顯示設置爲NULL。
若是STATISTICS_LEVEL設置爲BASIC禁用了監控特徵,自動統計收集將不會檢測過時的統計,此時須要手工收集。dom
3 須要手工收集的另外一個地方是系通通計,其不會自動收集。
對於固定表,如動態性能表,須要使用GATHER_FIXED_OBJECTS_STATS收集,這些表上的統計應該在數據庫具備有表明性的活動後收集。
統計收集考慮
==========================
1 統計收集使用取樣
不使用抽樣的統計收集須要全表掃描而且排序整個表,抽樣最小化收集統計的必要資源。
Oracle推薦設置DBMS_STATS的ESTIMATE_PERCENT參數爲DBMS_STATS.AUTO_SAMPLE_SIZE在達到必要的統計精確性的同時最大化性能。
2 並行統計收集
Oracle推薦設置DBMS_STATS的DEGREE參數爲DBMS_STATS.AUTO_DEGREE,該參數容許Oracle根據對象的大小和並行性初始化參數的設置選擇恰當的並行度。
聚簇索引,域索引,位圖鏈接索引不能並行收集。
3 分區對象的統計收集
對於分區表和索引,DBMS_STATS能夠收集單獨分區的統計和全局分區,對於組合分區,能夠收集子分區,分區,表/索引上的統計,分區統計的收集能夠經過聲明參數GRANULARITY。根據將優化的SQL語句,優化器能夠選擇使用分區統計或全局統計,對於大多數系統這兩種統計都是很重要的,Oracle推薦將GRANULARITY設置爲AUTO同時收集所有信息。
4 列統計和直方圖
當在表上收集統計時,DBMS_STATS收集表中列的數據分佈的信息,數據分佈最基本的信息是最大值和最小值,可是若是數據分佈是傾斜的,這種級別的統計對於優化器來講不夠的,對於傾斜的數據分佈,直方圖一般用來做爲列統計的一部分。
直方圖經過METHOD_OPT參數聲明,Oracle推薦設置METHOD_OPT爲FOR ALL COLUMNS SIZE AUTO,使用該值時Oracle自動決定須要直方圖的列以及每一個直方圖的桶數。也能夠手工設置須要直方圖的列以及桶數。
若是在使用DBMS_STATS的時候須要刪除表中的全部行,須要使用TRUNCATE代替drop/create,不然自動統計收集特徵使用的負載信息以及RESTORE_*_STATS使用的保存的統計歷史將丟失。這些特徵將沒法正常發揮做用。
5 肯定過時的統計
對於那些隨着時間更改的對象必須週期性收集統計,爲了肯定過時的統計,Oracle提供了一個表監控這些更改,這些監控默認狀況下在STATISTICS_LEVEL爲TYPICAL/ALL時啓用,該表爲USER_TAB_MODIFICATIONS。使用DBMS_STATS.FLUSH_DATABASE _MONITORING_INFO能夠馬上反映內存中超過監控的信息。在OPTIONS參數設置爲GATHER STALE or GATHER AUTO時,DBMS_STATS收集過時統計的對象的統計。
6 用戶定義統計
在建立了基於索引的統計後,應該在表上收集新的列統計,這能夠經過調用過程設置METHOD_OPT的FOR ALL HIDDEN COLUMNS。
7 什麼時候收集統計
對於增量更改的表,可能每月/每週只須要收集一次,而對於加載後表,一般在加載腳本中增長收集統計的腳本。對於分區表,若是僅僅是一個分區有了較大改動,只須要收集一個分區的統計,可是收集整個表的分區也是必要的。
系通通計
==========================
系通通計描述系統硬件的特徵,包括I/O和CPU。在選擇執行計劃時,優化器考慮查詢所需的CPU和I/O代價。系通通計容許優化器更加精確的評價CPU和IO代價,選擇更好的查詢計劃。
使用DBMS_STATS.GATHER_SYSTEM_STATS收集系通通計,Oracle推薦收集系通通計。收集系通通計須要DBA權限。
收集的優化器系通通計包括:
cpuspeedNW:表明無負載CPU速度,CPU速度爲每秒鐘CPU週期數;經過設置gathering_mode = NOWORKLOAD或手工設置統計;單位Millions/sec。
ioseektim:I/O查找時間=查找時間+延遲時間+OS負載時間;經過設置gathering_mode = NOWORKLOAD或手工設置統計;單位爲ms。
Iotfrspeed:I/O傳輸速度;經過設置gathering_mode = NOWORKLOAD或手工設置統計;單位爲Bytes/ms.
Cpuspeed:表明有負載CPU速度,CPU速度爲每秒鐘CPU週期數;經過設置gathering_mode =NOWORKLOAD,INTERVAL, START|STOP或手工設置統計;單位Millions/sec。
Maxthr:最大I/O吞吐量;經過設置gathering_mode =NOWORKLOAD,INTERVAL, START|STOP或手工設置統計;單位Bytes/sec.
Slavethr:服務I/O吞吐量是平均並行服務I/O吞吐量;經過設置gathering_mode = INTERVAL,START|STOP或手工設置統計;Bytes/sec.
Sreadtim:隨機讀取單塊的平均時間;經過設置gathering_mode =INTERVAL,START|STOP或手工設置統計;單位爲ms。
Mreadtim:順序讀取多塊的平均時間,經過設置經過設置gathering_mode = INTERVAL,START|STOP或手工設置統計;單位爲ms。
Mbrc: 多塊讀平均每次讀取的塊數量;經過設置經過設置gathering_mode = INTERVAL,START|STOP或手工設置統計;單位爲blocks。
系通通計的從新收集不會致使當前的SQL無效,只是全部的新SQL語句使用新的統計。
Oracle提供兩個選項收集統計:負載統計;非負載統計。
負載統計
==========================
在負載窗口的開始運行dbms_stats.gather_system_stats(’start’),而後運行dbms_stats.gather_system_stats(’stop’)結束負載窗口。
運行dbms_stats.gather_system_stats(’interval’, interval=>N),N表示N分鐘後系通通計收集結束。
運行dbms_stats.delete_system_stats()刪除負載統計。
非負載統計
==========================
運行不帶參數的dbms_stats.gather_system_stats()收集非負載統計,運行非負載統計時會有必定的I/O負載。在某些狀況下,非負載統計的值可能會保持默認,此時須要使用dbms_stats.set_system_stats設置。
管理統計
==========================
轉儲先前版本的統計
使用RESTORE過程轉儲先前版本的統計,這些過程使用一個時間戳做爲參數,包含統計時間的視圖包括:
1 DBA_OPTSTAT_OPERATIONS:其中包含了使用DBMS_STATS在模式/系統級別執行的統計操做;
2 *_TAB_STATS_HISTORY:包含了表統計更改的歷史。
舊的統計按期刷新,根據DBMS_STATS的ALTER_STATS_HISTORY_RETENTION過程設置而定,默認爲31天。
默認狀況下,若是STATISTICS_LEVEL爲TYPICAL/ALL,自動刷新啓用;不然須要使用PURGE_STAT手工刷新。
其餘轉儲與刷新相關的信息包括:
PURGE_STATS: 手工刷新超過某個時間戳的舊統計;
GET_STATS_HISTORY_RENTENTION: 獲得當前歷史統計保留值;
GET_STATS_HISTORY_AVAILABILTY: 獲得可用的最舊的統計的時間戳。
轉儲的限制:
1 不能轉儲用戶定義統計;
2 若是使用了ANALYZE收集,舊的統計將沒法轉儲。
導入/導出統計
==========================
導出統計前須要使用DBMS_STATS.CREATE_STAT_TABLE建立一個統計表保留統計,在表建立後可使用DBMS_STATS.EXPORT_*_STATS導出統計到自定義表,這些統計可使用DBMS_STATS.IMPORT_*_STATS從新導入。
也可使用IMP/EXP導到其餘數據庫。
轉儲統計與導入導出統計
使用轉儲的狀況:
1 恢復舊版本的統計;
2 但願數據庫管理統計歷史的保留和刷新;
使用EXPORT/IMPORT_*_STATS的狀況:
1 實驗各類值的不一樣狀況;
2 移動統計到不一樣數據庫;
3 保留統計數據更長的時間。
鎖住表和模式的統計
==========================
一旦統計被鎖住,將沒法在更改這些統計直到被解鎖。DBMS_STAT提供兩個過程用於解鎖,兩個用於加鎖:
1 LOCK_SCHEMA_STATS;?¤LOCK_TABLE_STATS;
2 UNLOCK_SCHEMA_STATS;?¤UNLOCK_TABLE_STATS;
設置統計
==========================
可使用SET_*_STATISTICS設置表,索引,列,系通通計。
使用動態取樣評價統計
==========================
動態取樣的目的是經過爲謂詞選擇性和表/索引統計肯定更加精確的估計提升服務器性能,估計越精確產生的性能更好。
可使用動態取樣的狀況:
1 在收集的統計不能使用或會致使嚴重的估計錯誤時估計單表的謂詞選擇性;
2 估計沒有統計的表/索引的統計;
3 估計統計過時的表和索引的統計;
動態取樣特徵由參數OPTIMIZER_DYNAMIC_SAMPLING控制,默認級別爲2。
動態取樣的工做機制
主要的性能特徵是編譯時,Oracle在編譯時決定一個查詢是否能經過取樣獲益,若是能夠,將用遞歸SQL隨機掃描一小部分表塊,而後應用相關的單表謂詞評價謂詞選擇性。
使用動態取樣的時間
使用動態取樣將獲益的狀況:
1 能夠發現更好的執行計劃;
2 取樣時間僅佔總時間的一小部分;
3 查詢將執行屢次;
取樣級別
==========================
範圍從1..10
缺失統計處理
==========================
當Oracle遇到丟失統計時,優化器動態必要的統計。在某些狀況下,Oracle沒法執行動態取樣,包括:遠程表/外部表,此時將使用默認統計。
缺失統計時的表默認值:
1 Cardinality:num_of_blocks * (block_size - cache_layer) / avg_row_len
2 Average row length:100字節;
3 Number of blocks:100或基於分區映射的實際值;
4 Remote cardinality:2000行;
5 Remote average row length:100字節;
缺失統計時的索引默認值:
Levels:1
Leaf blocks:25
Leaf blocks/key:1
Data blocks/key:1
Distinct keys:100
Clustering factor:800
gather_schema_stats
==========================
begin
dbms_stats.gather_schema_stats( wnname => 'SCOTT',
ptions => 'GATHER AUTO',
estimate_percent => dbms_stats.auto_sample_size,
method_opt => 'for all columns size repeat',
degree => 15 );
end;
options參數使用4個預設的方法:
gather——從新分析整個架構(Schema)。
gather empty——只分析目前尚未統計的表。
gather stale——只從新分析修改量超過10%的表(這些修改包括插入、更新和刪除)。
gather auto——從新分析當前沒有統計的對象,以及統計數據過時(變髒)的對象。相似於組合使用gather stale和gather empty。
注意,不管gather stale仍是gather auto,都要求進行監視。
若是你執行一個alter table xxx monitoring命令,Oracle會用dba_tab_modifications視圖來跟蹤發生變更的表。
這樣一來,你就確切地知道,自從上一次分析統計數據以來,發生了多少次插入、更新和刪除操做。
SELECT * FROM Sys.Dba_Tab_Modifications WHERE Table_Owner = 'SCOTT';
使用alter table xxx monitoring命令來實現Oracle表監視時,須要使用dbms_stats中的auto選項。
auto選項根據數據分佈以及應用程序訪問列的方式(例如經過監視而肯定的一個列的工做量)
來建立直方圖。使用method_opt=>’auto’相似於在dbms_stats的option參數中使用gather auto。
begin
dbms_stats.gather_schema_stats(ownname => 'SCOTT',
estimate_percent => dbms_stats.auto_sample_size,
method_opt => 'for all columns size auto',
degree => 7);
end;
estimate_percent選項
如下estimate_percent參數是一種比較新的設計,它容許Oracle的dbms_stats在收集統計數據時,自動估計要採樣的一個segment的最佳百分比:
estimate_percent => dbms_stats.auto_sample_size
要驗證自動統計採樣的準確性,你可檢視dba_tables sample_size列。一個有趣的地方是,在使用自動採樣時,Oracle會爲一個樣本尺寸選擇5到20的百分比。記住,統計數據質量越好,CBO作出的決定越好。
method_opt選項
dbms_stats的method_opt參數尤爲適合在表和索引數據發生變化時刷新統計數據。method_opt參數也適合用於判斷哪些列須要直方圖(histograms)。
某些狀況下,索引內的各個值的分佈會影響CBO是使用一個索引仍是執行一次全表掃描的決策。例如,假如在where子句中指定的值的數量不對稱,全表掃描就顯得比索引訪問更經濟。
若是你有一個高度傾斜的索引(某些值的行數不對稱),就可建立Oracle直方圖統計。但在現實世界中,出現這種狀況的機率至關小。使用CBO時,最多見的錯誤之一就是在CBO統計中沒必要要地引入直方圖。根據經驗,只有在列值要求必須修改執行計劃時,才應使用直方圖。
爲了智能地生成直方圖,Oracle爲dbms_stats準備了method_opt參數。在method_opt子句中,還有一些重要的新選項,包括skewonly,repeat和auto:method_opt=>'for all columns size skewonly'
method_opt=>'for all columns size repeat'
method_opt=>'for all columns size auto'
skewonly選項會耗費大量處理時間,由於它要檢查每一個索引中的每一個列的值的分佈狀況。
假如dbms_stat發現一個索引的各個列分佈得不均勻,就會爲那個索引建立直方圖,幫助基於代價的SQL優化器決定是進行索引訪問,仍是進行全表掃描訪問。例如,在一個索引中,假定有一個列在50%的行中,那麼爲了檢索這些行,全表掃描的速度會快於索引掃描。
--*************************************************************
-- SKEWONLY option—Detailed analysis
--
-- Use this method for a first-time analysis for skewed indexes
-- This runs a long time because all indexes are examined
--*************************************************************
begin
dbms_stats.gather_schema_stats(ownname => 'SCOTT',
estimate_percent => dbms_stats.auto_sample_size,
method_opt => 'for all columns size skewonly',
degree => 7);
end;
從新分析統計數據時,使用repeat選項,從新分析任務所消耗的資源就會少一些。使用repeat選項時,只會爲現有的直方圖從新分析索引,再也不搜索其餘直方圖機會。按期從新分析統計數據時,你應該採起這種方式。
--**************************************************************
-- REPEAT OPTION - Only reanalyze histograms for indexes
-- that have histograms
--
-- Following the initial analysis, the weekly analysis
-- job will use the 「repeat」 option. The repeat option
-- tells dbms_stats that no indexes have changed, and
-- it will only reanalyze histograms for
-- indexes that have histograms.
--**************************************************************
begin
dbms_stats.gather_schema_stats(ownname => 'SCOTT',
estimate_percent => dbms_stats.auto_sample_size,
method_opt => 'for all columns size repeat',
degree => 7);
end;
Oracle中關於表的統計信息是在數據字典中的,能夠下SQL查詢到:
SELECT Table_Name,Num_Rows,Blocks,Empty_Blocks,Avg_Space,Chain_Cnt,Avg_Row_Len,Sample_Size,Last_Analyzed
FROM Dba_Tables WHERE wner = 'SCOTT' ;
這是對命令與工具包的一些總結
一、對於分區表,建議使用DBMS_STATS,而不是使用Analyze語句。
a) 能夠並行進行,對多個用戶,多個Table
b) 能夠獲得整個分區表的數據和單個分區的數據。
c) 能夠在不一樣級別上Compute Statistics:單個分區,子分區,全表,全部分區 ,但不收集聚簇統計
d) 能夠倒出統計信息
e) 能夠用戶自動收集統計信息
二、DBMS_STATS的缺點
a) 不能Validate Structure
b) 不能收集CHAINED ROWS, 不能收集CLUSTER TABLE的信息,這兩個仍舊須要使用Analyze語句。
c) DBMS_STATS 默認不對索引進行Analyze,由於默認Cascade是False,須要手工指定爲True
三、對於External Table,Analyze不能使用,只能使用DBMS_STATS來收集信息。
GATHER_TABLE_STATS
==========================
DBMS_STATS.gather_table_stats
(ownname varchar2,
tabname varchar2,
partname varchar2 default null,
estimate_percent number default to_estimate_percent_type(get_param('ESTIMATE_PERCENT')),
block_sample boolean default FALSE,
method_opt varchar2 default get_param('METHOD_OPT'),
degree number default to_degree_type(get_param('DEGREE')),
granularity varchar2 default get_param('GRANULARITY'),
cascade boolean default to_cascade_type(get_param('CASCADE')),
stattab varchar2 default null, statid varchar2 default null,
statown varchar2 default null,
no_invalidate boolean default to_no_invalidate_type(get_param('NO_INVALIDATE')),
stattype varchar2 default 'DATA',
force boolean default FALSE);
參數說明:
ownname: 要分析表的擁有者
tabname: 要分析的表名.
partname: 分區的名字,只對分區表或分區索引有用.
estimate_percent:採樣行的百分比,取值範圍[0.000001,100],null爲所有分析,不採樣. 常量:DBMS_STATS.AUTO_SAMPLE_SIZE是默認值,由oracle決定最佳取採樣值.
block_sapmple:是否用塊採樣代替行採樣.
method_opt: 決定histograms信息是怎樣被統計的.method_opt的取值以下:
for all columns:統計全部列的histograms.
for all indexed columns:統計全部indexed列的histograms.
for all hidden columns:統計你看不到列的histograms
for columns <list> SIZE <N> | REPEAT | AUTO | SKEWONLY:
統計指定列的histograms.N的取值範圍[1,254]; R
EPEAT上次統計過的histograms;
AUTO由oracle決定N的大小;
SKEWONLY multiple end-points with the same value which is what we define by "there is skew in the data
degree: 設置收集統計信息的並行度.默認值爲null.
granularity:Granularity of statistics to collect ,only pertinent if the table is partitioned.
cascade: 是收集索引的信息.默認爲falase.
stattab 指定要存儲統計信息的表,statid若是多個表的統計信息存儲在同一個stattab中用於進行區分.statown存儲統計信息表的擁有者.以上三個參數若不指定,統計信息會直接更新到數據字典.
no_invalidate: Does not invalidate the dependent cursors if set to TRUE. The procedure invalidates the dependent cursors immediately if set to FALSE.
force: 即便表鎖住了也收集統計信息
例子:
execute dbms_stats.gather_table_stats(ownname => 'owner',
tabname => 'table_name' ,
estimate_percent => null ,
method_opt => 'for all indexed columns' ,
cascade => true);
GATHER_INDEX_STATS
==========================
BEGIN
SYS.DBMS_STATS.GATHER_INDEX_STATS (OwnName => 'ABC',
IndName => 'IDX_FUNC_ABC',
Estimate_Percent => 10,
Degree => SYS.DBMS_STATS.DEFAULT_DEGREE,
No_Invalidate => FALSE);
END;
---------------------------------------
10g自動收集統計信息
---------------------------------------
從10g開始,Oracle在建庫後就默認建立了一個名爲GATHER_STATS_JOB的定時任務,用於自動收集CBO的統計信息。
這個自動任務默認狀況下在工做日晚上10:00-6:00和週末全天開啓。
調用DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC收集統計信息。該過程首先檢測統計信息缺失和陳舊的對象。而後肯定優先級,再開始進行統計信息。
能夠經過如下查詢這個JOB的運行狀況:
SELECT * FROM Dba_Scheduler_Jobs WHERE Job_Name = 'GATHER_STATS_JOB';
其實同在10點運行的Job還有一個AUTO_SPACE_ADVISOR_JOB:
SELECT Job_Name, Last_Start_Date FROM Dba_Scheduler_Jobs;
JOB_NAME LAST_START_DATE
------------------------------ ------------------------------------
AUTO_SPACE_ADVISOR_JOB 30-OCT-08 10.00.01.463000 PM +08:00
GATHER_STATS_JOB 30-OCT-08 10.00.01.463000 PM +08:00
然而這個自動化功能已經影響了不少系統的正常運行,晚上10點對於大部分生產系統也並不是空閒時段。
而自動分析可能致使極爲嚴重的閂鎖競爭,進而可能致使數據庫Hang或者Crash。
因此建議最好關閉這個自動統計信息收集功能:
關閉及開啓自動蒐集功能,有兩種方法,分別以下:
方法一:
exec dbms_scheduler.disable('SYS.GATHER_STATS_JOB');
exec dbms_scheduler.enable('SYS.GATHER_STATS_JOB');
方法二:
alter system set "_optimizer_autostats_job"=false scope=spfile;
alter system set "_optimizer_autostats_job"=true scope=spfile;
---------------------------------------
查看統計
---------------------------------------
表/索引/列上的統計
DBA_TABLES
DBA_OBJECT_TABLES
DBA_TAB_STATISTICS
DBA_TAB_COL_STATISTICS
DBA_TAB_HISTOGRAMS
DBA_INDEXES
DBA_IND_STATISTICS
DBA_CLUSTERS
DBA_TAB_PARTITIONS
DBA_TAB_SUBPARTITIONS
DBA_IND_PARTITIONS
DBA_IND_SUBPARTITIONS
DBA_PART_COL_STATISTICS
DBA_PART_HISTOGRAMS
DBA_SUBPART_COL_STATISTICS
DBA_SUBPART_HISTOGRAMS
---------------------------------------
直方圖統計
---------------------------------------
直方圖的類型存儲在*TAB_COL_STATISTICS視圖的HISTOGRAM列上。
------------------------------------------------------------------------------
bde_last_analyzed.sql - Verifies CBO Statistics
------------------------------------------------------------------------------
bde_last_analyzed.sql verifies the CBO statistics in the data dictionary for all tables, indexes, and partitions. It also validates the statistics on tables and indexes owned by 'SYS'.
The 5 generated reports bde_last_analyzed_xxx.html, present the total of tables and indexes analyzed per module and per date.
Script. bde_last_analyzed.sql provided in this Note can be used on any 8i, 9i, 10g, 11g or higher database, including Oracle Apps 11i and R12 instances
若是是ERP數據庫,則用APPS鏈接,不然用其餘任何SYS權限用戶鏈接均可以
#sqlplus <user>/<pwd>
SQL> START bde_last_analyzed.sql
Review spool output files bde_last_analyzed_xxx.html files. Spool files get created on same directory from which this script. is executed. On NT, files may get created under $ORACLE_HOME/bin.
If some modules have not been analyzed, or they have but not recently, these Apps objects must be analyzed using FND_STATS or coe_stats.sql if belonging to Oracle Apps. Otherwise use DBMS_STATS.
If Oracle Apps, use corresponding concurrent program with an estimate of 10%, or execute equivalent FND_STATS procedure from SQL*Plus:
SQL> exec fnd_stats.gather_schema_statistics('APPLSYS'); Where 'APPLSYS' is the module (schema) that requires new statistics.
If only a few tables require to have their statistics gathered, use the corresponding concurrent program to gather stats by table, or execute equivalent FND_STATS procedure from SQL*Plus:
SQL> exec fnd_stats.gather_table_stats('MRP','MRP_FORECAST_DATES');
Where 'MRP' is the schema owner, and 'MRP_FORECAST_DATES' is the table name. This syntax is only for non-partitioned Tables.
If any Partitioned Table requires its Global Stats being rebuilt, it is because at some point you gathered Stats on the table using a granularity of PARTITION. See second method below:
begin
dbms_stats.delete_table_stats(ownname => 'APPLSYS', tabname => 'WF_ITEM_ACTIVITY_STATUSES');
fnd_stats.gather_table_stats (ownname => 'APPLSYS', tabname => 'WF_ITEM_ACTIVITY_STATUSES',
granularity => 'DEFAULT');
end;
/
Once you fix your stats, be sure to ALWAYS use the granularity of DEFAULT for partitioned tables.
If you want to execute this bde_last_analyzed.sql script. against only one schema, modify DEF SCHEMA code line.
---------------------------------------
分區表的統計信息實例
---------------------------------------
ORATEA ORACLE的統計信息在執行SQL的過程當中扮演着很是重要的做用,並且ORACLE在表的各個層次都會有不一樣的統計信息,經過這些統計信息來描述表的,列的各類各樣的統計信息。下面經過一個複合分區表來講明一些常見的和常見的統計信息。
SQL>
create table test
partition by range(object_id)
subpartition by hash(object_type) subpartitions 4
(partition p1 values less than(10000),
partition p2 values less than(20000),
partition p3 values less than(30000),
partition p4 values less than(maxvalue))
as
select * from dba_objects;
表已建立。
sql>
BEGIN
dbms_stats.gather_table_stats(ownname => 'SCOTT',
tabname => 'TEST',
estimate_percent => 100,
block_sample => FALSE,
method_opt => 'FOR ALL COLUMNS SIZE 10',
granularity => 'ALL',
cascade => TRUE);
END;
1,表級的統計信息
SQL> select table_name,num_rows,blocks,empty_blocks,avg_space from user_tables where table_name = 'TEST';
TABLE_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE
------------------------------ ---------- ---------- ------------ ----------
TEST 50705 788 0 0
2,表上列的統計信息
SQL> select table_name,column_name,num_distinct,density from user_tab_columns where table_name = 'TEST';
TABLE_NAME COLUMN_NAME NUM_DISTINCT DENSITY
------------------------------ ------------------------------ ------------ ----------
TEST OWNER 25 .365014295
TEST OBJECT_NAME 30275 .000039205
TEST SUBOBJECT_NAME 191 .015657993
TEST OBJECT_ID 50705 .000019722
TEST DATA_OBJECT_ID 4334 .000248075
TEST OBJECT_TYPE 42 .271207855
TEST CREATED 2305 .001608457
TEST LAST_DDL_TIME 2369 .001566737
TEST TIMESTAMP 2412 .001610251
TEST STATUS 2 .000009861
TEST TEMPORARY 2 .000009861
TEST GENERATED 2 .000009861
TEST SECONDARY 2 .000009861
13 rows selected.
3,表上列的直方圖信息
SQL>
select table_name,column_name,endpoint_number,endpoint_value
from user_tab_histograms
where table_name = 'TEST'
and column_name = 'OBJECT_ID';
TABLE_NAME COLUMN_NAM ENDPOINT_NUMBER ENDPOINT_VALUE
---------- ---------- --------------- --------------
TEST OBJECT_ID 0 2
TEST OBJECT_ID 1 5160
TEST OBJECT_ID 2 10587
TEST OBJECT_ID 3 15658
TEST OBJECT_ID 4 20729
TEST OBJECT_ID 5 25800
TEST OBJECT_ID 6 30870
TEST OBJECT_ID 7 35940
TEST OBJECT_ID 8 41089
TEST OBJECT_ID 9 46821
TEST OBJECT_ID 10 53497
4,分區的統計信息
SQL>
select partition_name,num_rows,blocks,empty_blocks,avg_space
from user_tab_partitions
where table_name = 'TEST';
PARTITION_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS AVG_SPACE
--------------- ---------- ---------- ------------ ----------
P1 9581 140 0 0
P2 9973 164 0 0
P3 10000 158 0 0
P4 21151 326 0 0
5,分區上列的統計信息
SQL> select column_name,num_distinct,density,num_nulls
from user_part_col_statistics
where table_name = 'TEST'
and partition_name = 'P1';
COLUMN_NAME NUM_DISTINCT DENSITY NUM_NULLS
--------------- ------------ ---------- ----------
OWNER 7 .000052187 0
OBJECT_NAME 7412 .000156925 0
SUBOBJECT_NAME 26 .47017301 9496
OBJECT_ID 9581 .000104373 0
DATA_OBJECT_ID 1765 .000664385 7780
OBJECT_TYPE 34 .18494854 0
CREATED 913 .001977449 0
LAST_DDL_TIME 994 .001882695 0
TIMESTAMP 982 .001928775 0
STATUS 2 .000052187 0
TEMPORARY 2 .000052187 0
GENERATED 2 .000052187 0
SECONDARY 1 .000052187 0
6,分區上列的直方圖信息
SQL> select column_name,bucket_number,endpoint_value
from user_part_histograms
where table_name = 'TEST'
and partition_name = 'P1'
and column_name = 'OBJECT_ID';
COLUMN_NAME BUCKET_NUMBER ENDPOINT_VALUE
--------------- ------------- --------------
OBJECT_ID 0 2
OBJECT_ID 1 1005
OBJECT_ID 2 1963
OBJECT_ID 3 2921
OBJECT_ID 4 3888
OBJECT_ID 5 4859
OBJECT_ID 6 5941
OBJECT_ID 7 6899
OBJECT_ID 8 7885
OBJECT_ID 9 8864
OBJECT_ID 10 9999
7,子分區的統計信息
SQL> select subpartition_name,num_rows,blocks,empty_blocks
from user_tab_subpartitions
where table_name = 'TEST'
and partition_name = 'P1';
SUBPARTITION_NAME NUM_ROWS BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ---------- ------------
SYS_SUBP21 3597 50 0
SYS_SUBP22 3566 52 0
SYS_SUBP23 637 11 0
SYS_SUBP24 1781 27 0
8,子分區上的列的統計信息
SQL> select column_name,num_distinct,density
from user_subpart_col_statistics
where table_name = 'TEST'
and subpartition_name = 'SYS_SUBP21';
COLUMN_NAME NUM_DISTINCT DENSITY
--------------- ------------ ----------
OWNER 6 .000139005
OBJECT_NAME 3595 .000278319
SUBOBJECT_NAME 4 .014285714
OBJECT_ID 3597 .000278009
DATA_OBJECT_ID 155 .006451613
OBJECT_TYPE 8 .000139005
CREATED 751 .002392334
LAST_DDL_TIME 784 .002302524
TIMESTAMP 768 .00235539
STATUS 1 .000139005
TEMPORARY 2 .000139005
GENERATED 2 .000139005
SECONDARY 1 .000139005
9,子分區上的列的直方圖信息
SQL> select column_name,bucket_number,endpoint_value
from user_subpart_histograms
where table_name = 'TEST'
and subpartition_name = 'SYS_SUBP21'
and column_name = 'OBJECT_ID';
COLUMN_NAME BUCKET_NUMBER ENDPOINT_VALUE
--------------- ------------- --------------
OBJECT_ID 0 208
OBJECT_ID 1 1525
OBJECT_ID 2 2244
OBJECT_ID 3 2892
OBJECT_ID 4 3252
OBJECT_ID 5 4047
OBJECT_ID 6 5238
OBJECT_ID 7 6531
OBJECT_ID 8 7661
OBJECT_ID 9 8474
OBJECT_ID 10 9998
咱們對這個複合分區分析以後產生了上面這九種不一樣層次的統計信息。CBO想要得要一個高效的執行計劃須要如此多的統計信息.
1. 理解什麼是統計信息
優化器統計信息就是一個更加詳細描述數據庫和數據庫對象的集合,這些統計信息被用於查詢優化器,讓其爲每條SQL語句選擇最佳的執行計劃。優化器統計信息包括:
· 表的統計信息
o 行數
o Block數
o 行平均長度
· 列的統計信息
o 列中不一樣值的數量
o 列中null的數量
o 數據分佈(柱狀圖/直方圖)
· 索引的統計信息
o 葉子塊的數量
o 索引的高度
o 聚簇因子(clustering factor)
· 系統的統計信息
o I/O性能和利用
o CPU性能和利用
優化器統計信息存儲在下列數據字典中
· DBA_TABLES
· DBA_OBJECT_TABLES
· DBA_TAB_STATISTICS
· DBA_TAB_COL_STATISTICS
· DBA_TAB_HISTOGRAMS
· DBA_INDEXES
· DBA_IND_STATISTICS
· DBA_CLUSTERS
· DBA_TAB_PARTITIONS
· DBA_TAB_SUBPARTITIONS
· DBA_IND_PARTITIONS
· DBA_IND_SUBPARTITIONS
· DBA_PART_COL_STATISTICS
· DBA_PART_HISTOGRAMS
· DBA_SUBPART_COL_STATISTICS
· DBA_SUBPART_HISTOGRAMS
· INDEX_STATS 存儲ANALYZE ..VALIDATE STRUCTURE統計信息
· AUX_STATS$ 存儲CPU統計信息
· X$KCFIO 存儲I/O統計信息
由於數據庫中的對象會常常的變化,因此統計信息必須有規律的更新以便更加準確的描述這些數據庫對象。統計信息默認是由ORACLE自動維護的,不過咱們也能夠用DBMS_STATS包手動收集統計信息。DBMS_STATS包一樣提供了過程來維護統計信息。關於DBMS_STATS包更詳細的描述請參閱官方文檔PL/SQL Packages and Types Reference部分。
2. 自動收集統計信息
Oracle10g中,在安裝Oracle的時候,就默認建立了一個名爲GATHER_STATS_JOB的job來自動收集優化器統計信息。這個job收集數據庫中全部對象的統計信息。默認的狀況下這個job是週一到週五天天晚上10點到次日早上6點以及整個週末來收集統計信息。
能夠查看DBA_SCHEDULER_JOBS, DBA_SCHEDULER_PROGRAMS,DBA_SCHEDULER_WINDOWS,DBA_SCHEDULER_JOB_RUN_DETAILS等視圖來查看JOB設置以及運行信息。
自動收集過時的統計信息依賴於表監控特徵,在Oracle10g中表監控默認是開啓的,同時它也依賴STATISTICS_LEVEL參數的值,10g中默認爲typical,只有將STATISTICS_LEVEL參數設置爲ALL或者TYPICAL才能讓ORACLE識別過時的統計信息。
3. 關閉自動收集統計信息
在某些狀況下,咱們想關閉自動收集統計信息那麼咱們能夠利用以下方法:
BEGIN
DBMS_SCHEDULER.DISABLE('GATHER_STATS_JOB');
END;
/
4. 什麼時候該手動收集統計信息
有時候自動收集統計並不合適,由於自動收集統計信息是在午夜運行的,然而因爲對象是在白天被修改了,致使致使的統計信息變得陳舊,這裏有2種這類對象:
· 白天常常被delete,或者truncated以後又rebuild的表(常常變化的表)
· 批量操做以後有10%或者以上的數據被更改的表(批量處理的表)
· 對於常常變化的表,能夠將其統計信息設置爲null,當ORACLE遇到一個表沒有統計信息,ORACLE會動態採樣以便爲查詢優化器收集必要的統計信息。動態採樣這個特徵受到參數optimizer_dynamic_sampling的控制,它的默認值爲2,同時呢optimizer_mode也能控制動態採樣,可將其設置爲all.
以SCOTT用戶下的DEPT表爲例,將一個表的統計信息設置爲null的方法以下:
BEGIN
DBMS_STATS.DELETE_TABLE_STATS('SCOTT','DEPT');
DBMS_STATS.LOCK_TABLE_STATS('SCOTT','DEPT');
END;
/
咱們也能夠在表具備典型的,表明性的時候收集統計信息,而且鎖住其統計信息,由於在夜晚自動收集的統計信息未必適用於白天的負載,而典型的統計信息具備表明意義,因此這個時候採起lock其典型的統計信息更能讓CBO選擇更優的執行計劃。
至於上面的兩種方法用哪一種,這個還須要根據業務,實際狀況分析之。
· 對於批量處理的表 ,應該在批量處理完成的時候當即對其收集統計信息,能夠將收集統計信息的腳本綁定到批量處理的腳本中。
· 對於外部表,只能經過gather_table_stats過程來收集統計信息,而且外部表不支持取樣,因此須要把gather_table_stats中的estimate_percent設置爲null。
· 系統的統計信息也須要手動收集,由於這些信息是不會自動收集的。
· 對於固定對象,好比說動態性能表,須要手動的執行gather_fixed_objects_stats過程來收集。固定的對象反映了當前數據庫的活動。當數據庫活動處於具備表明性的時候,就應該收集這類統計信息。
5. 鎖住/解鎖統計信息
· LOCK_SCHEMA_STATS
· LOCK_TABLE_STATS
· UNLOCK_SCHEMA_STATS
· UNLOCK_TABLE_STATS
6. 手動收集統計信息
· 若是你選擇手動收集統計信息,那麼你須要手動的收集全部用戶的統計信息,包括系統用戶。若是你數據庫中的數據是有規律的變化的,那麼你能夠有規律的收集統計信息,以便統計信息可以準確的反映數據庫中的對象的特徵。
· 能夠利用DBMS_STATS包,來收集表,索引,列,以及分區表的統計信息,DBMS_STATS不能收集CLUSTER 的統計信息,不過能夠收集單個表來代替收集整個CLUSTER的統計信息。
· 當你收集表,列,索引的統計信息的時候,若是ORACLE在數據字典中發現這個對象已經收集了統計信息,那麼ORACLE會更新已經存在的統計信息,舊的統計信息會被保存下來,若是你願意還能還原舊的統計信息。
· 你可使用DBMS_STATS.GATHER_DICTIONARY_STATS來收集系統用戶的統計信息,這個過程收集全部的系統用戶的統計信息,包括SYS和SYSTEM,以及其餘用戶,好比CTXSYS,DRSYS。
· 當數據庫對象的統計信息被更新以後,ORACLE會使已經解析的SQL語句做廢,當再次運行該SQL語句的時候,ORACLE會從新解析該SQL,優化器會自動的根據新的統計信息選擇一條新的執行計劃。對於分佈式的數據庫,不會做廢。
· 收集統計信息的過程
o GATHER_INDEX_STATS --收集索引統計信息
o GATHER_TABLE_STATS --收集表,列,索引統計信息
o GATHER_SCHEMA_STATS --收集schema全部對象統計信息
o GATHER_DICTIONARY_STATS –-收集全部系統用戶的統計信息
o GATHER_DATABASE_STATS --收集數據庫全部對象統計信息
· 咱們利用上面的過程收集統計信息的時候有幾個須要關心的參數
o 採樣
o 並行
o 分區
o 列統計以及直方圖/柱狀圖
o 過時的統計
o 自定義統計
? 在收集統計信息的操做過程當中咱們可使用採樣來評估統計信息。採樣對於收集統計信息來講是一項很重要的技術。若是在收集統計信息的時候不使用採樣,那麼就須要對錶進行全表掃描,以及排序整個表。經過採樣能夠下降收集必要的統計信息所花費的資源。
控制採樣的參數是ESTIMATE_PERCENT,採樣的參數能夠設置任意值(固然要在範圍內),不過ORACLE公司推薦設置ESTIMATE_PERCENT爲DBMS_STATS.AUTO_SAMPLE_SIZE。
AUTO_SAMPLE_SILE可讓ORACLE本身決定最好的採樣值,由於不一樣類型(table,index,column)的統計信息有不一樣的需求。採樣的例子:
EXEC DBMS_STATS.GATHER_SCHEMA_STATS(‘SCOTT’,DBMS_STATS.AUTO_SAMPLE_SIZE);
當ESTIMATE_PERCENT參數是手動指定的,若是手動指定的參數太小,不能收集到足夠的信息,那麼DBMS_STATS可能會自動增加ESTIMATE_PERCENT的值,這樣就能確保收集到足夠的統計信息。
? 咱們既能夠串行的收集統計信息,也能夠並行的收集統計信息。參數DEGREE控制DBMS_STATS是否使用並行特徵。ORACLE公司推薦將DEGREE參數設置爲DBMS_STATS.AUTO_DEGREE。這樣設置事後,ORACLE就可以根據OBJECT的SIZE,以及與並行有關的init參數來決定一個恰當的並行度,收集統計信息。注意:cluster index,domain index,bitmap join index不能使用並行特徵。
? 對於分區表和分區索引,DBMS_STATS既能夠單獨的收集分區統計信息,也能夠收集整個表/索引的統計信息。對於組合分區,DBMS_STATS也可以收集子分區,分區,以及整個表/索引的統計信息。參數GRANULARITY控制分區統計信息的收集。由於分區統計信息,全局統計信息對於大多數系統來講都是很是重要的,因此ORACLE公司推薦將其設置爲AUTO來收集分區,以及全局的統計信息。
? 當對錶收集統計信息的時候,DBMS_STATS會收集列的數據分佈信息。數據分佈最基本的統計信息就是這個列的最大值與最小值。若是這一列是傾斜的,那麼優化器僅僅根據列最大值與最小值是沒法制定出準確的執行計劃的。對於傾斜的數據分佈,咱們能夠收集列的直方圖/柱狀圖統計信息,這樣可讓優化器制定出更加準確的執行計劃。
參數METHOD_OPT控制柱狀圖的收集。ORACLE公司推薦設置METHOD_OPT爲FOR ALL COLUMNS SIZE AUTO。這樣設置事後ORACLE會自動的判斷哪一列須要收集柱狀圖,而且自動的設置柱狀圖的bucket。你一樣能夠手動的設置哪一列須要收集柱狀圖,以及柱狀圖的bucket。
? 爲了知道統計信息是否過時,ORACLE提供了表監控功能。將init參數STATISTICS_LEVEL設置爲ALL或者TYPICAL(默認),就開啓了表監控的功能(10g已經不須要alter table monitor了)。表監控功能跟蹤表的insert,update,delete,truncate,操做,而且記錄在DBA_TAB_MODIFICATIONS視圖裏面。咱們在查詢DBA_TAB_MODIFICATIONS視圖的時候有可能查詢不到結果,或者查詢的結果不許確,這個時候須要用DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO過程將內存中的信息刷新到
該視圖中。OPTIONS參數設置爲GATHER STALE或者GATHER AUTO,就會讓DBMS_STATS判斷表的統計信息是否過時(注意GATHER_TABLE_STATS中沒有這個參數,只有GATHER_DATABASE_STATS,GATHER_SCHEMA_STATS過程當中有這個參數)。判斷表的統計信息是否過時的依據是是否有10%以上的數據被修改過,若是被修改過了,那麼ORACLE就認爲以前的統計信息過時了,ORACLE會從新收集統計信息。
? 在咱們建立了函數索引以後,咱們要爲列收集統計信息,這個時候咱們須要設置參數METHOD_OPT爲FOR ALL HIDDEN COLUMNS。
7. 收集統計信息的策略
一般狀況下,咱們會將ORACLE自動收集統計信息功能給關閉,咱們會採用手動的方式給數據庫收集統計信息。至於收集統計信息的策略須要根據系統來肯定。下面說說幾種常見的狀況:
· 若是你係統中的表的數據是增量(有規律)的增長,也就是說你幾乎不作任何的批量處理操做,好比批量刪除,批量加載操做。對於這樣的表收集統計信息是很是簡單的。你能夠經過查看DBA_TAB_MODIFICATIONS視圖來觀察表的變化狀況,觀察表中數據量的變化是否超過了10%,而且記錄下天數。這樣你就能夠每隔這樣的時間間隔對其收集一次統計信息。你能夠用CRONTAB,或者JOB調用GATHER_SCHEMA_STATS或者GATHER_TABLE_STATS過程來收集統計信息。
· 對於常常批量操做的表,那麼表的統計信息就必須在批量操做以後對其收集統計信息。
· 對於分區表,一般只有一個分區被修改,這種狀況下能夠只收集單獨分區的統計信息,不過收集整個表的統計信息仍是很是有必要的。
· 最後我會給出兩個腳本,判斷該表是否須要收集統計信息。
8. 收集統計信息的一些例子
例子1對錶收集統計信息
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT',
tabname => 'DEPT',
estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
method_opt => 'for all columns size repeat',
degree => DBMS_STATS.AUTO_DEGREE,
cascade=>TRUE
);
END;
/
上面的例子收集SCOTT.DEPT表的統計信息。這裏面值得關注的一個參數就是method_opt。這個參數控制是否收集列的直方圖信息。一般狀況下,是不會收集直方圖的,關於直方圖不是三言兩語能夠說明白的。它的四個選項method_opt=>'for all columns size skewonly'
ORACLE會根據數據分佈收集直方圖
method_opt=>'for all columns size repeat'
只有之前收集過直方圖,纔會收集直方圖信息,因此通常咱們會設置method_opt 爲repeat
method_opt=>'for all columns size auto'
ORACLE會根據數據分佈以及列的workload來肯定是否收集直方圖
method_opt=>'for all columns size interger'
咱們本身指定一個bucket值
例子2對某一個schma收集統計信息
BEGIN
DBMS_STATS.GATHER_SCHEMA_STATS(ownname => 'SCOTT',
estimate_percent =>DBMS_STATS.AUTO_SAMPLE_SIZE,
options => 'gather auto',
degree => DBMS_STATS.AUTO_DEGREE,
method_opt => 'for all columns size repeat',
cascade => TRUE
);
END;
/
上面的例子收集SCOTT模式下全部對象的統計信息。裏面值得注意的一個參數就是options。前面已經講到過,他與表監控有關。它有四個選項
Options =>’gather’ 收集全部對象的統計信息
Options =>’gather empty’ 只收集還沒被統計的表
Options =>’gather stale’ 只收集修改量超過10%的表
Options =>’gather auto’ 至關於empty+stale ,因此咱們通常設置爲AUTO。
例子3 對一個分區表收集統計信息
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(ownname => 'ROBINSON',
tabname => 'P_TEST',
estimate_percent => DBMS_STATS.AUTO_SAMPLE_SIZE,
method_opt => 'for all columns size repeat',
degree => DBMS_STATS.AUTO_DEGREE,
granularity => 'ALL',
cascade=>TRUE
);
END;
/
上面的例子收集ROBINSON.P_TEST表的統計信息。裏面值得注意的一個參數就是granularity,他有7個選項。
granularity => 'ALL' 收集分區,子分區,全局的統計信息
granularity => 'AUTO' 這個是默認的設置,ORACLE會根據分區類型來決定用ALL,GLOBAL AND PARTITION ,仍是其餘的
granularity => 'DEFAULT' 這個是過時了的
granularity => 'GLOBAL' 收集全局統計信息
granularity => 'GLOBAL AND PARTITION' 收集全局,分區統計信息,可是不收集子分區統計信息
granularity => 'PARTITION' 收集分區統計信息
granularity => 'SUBPARTITION' 收集子分區統計信息
固然咱們能夠指定partname,本身控制對哪一個分區收集統計信息
9. 列出表須要收集統計信息的腳本
普通表
set serveroutput on
declare
-----select OVER THE Change RATE TABLES---------------
cursor overchangerate is
select a.table_owner, a.table_name, a.inserts,a.updates,a.deletes ,b.num_rows
from dba_tab_modifications a, dba_tables b
where a.table_name = b.table_name
and table_owner not in
('SYS', 'SYSTEM', 'SYSMAN', 'DMSYS', 'OLAPSYS', 'XDB',
'EXFSYS', 'CTXSYS', 'WMSYS', 'DBSNMP', 'ORDSYS',
'OUTLN', 'TSMSYS', 'MDSYS')
and inserts > 0 and partitioned='NO' and a.inserts/decode(b.num_rows,0,1,b.num_rows)>=0.1
or a.table_name = b.table_name
and table_owner not in
('SYS', 'SYSTEM', 'SYSMAN', 'DMSYS', 'OLAPSYS', 'XDB',
'EXFSYS', 'CTXSYS', 'WMSYS', 'DBSNMP', 'ORDSYS',
'OUTLN', 'TSMSYS', 'MDSYS')
and updates > 0 and partitioned='NO' and a.updates/decode(b.num_rows,0,1,b.num_rows)>=0.1 or
a.table_name = b.table_name
and table_owner not in
('SYS', 'SYSTEM', 'SYSMAN', 'DMSYS', 'OLAPSYS', 'XDB',
'EXFSYS', 'CTXSYS', 'WMSYS', 'DBSNMP', 'ORDSYS',
'OUTLN', 'TSMSYS', 'MDSYS')
and deletes > 0 and partitioned='NO' and a.deletes/decode(b.num_rows,0,1,b.num_rows)>=0.1 ;
----select the unanalyzed table---------------
cursor nullmonitor is
select owner, table_name
from dba_tables
where owner not in ('SYS', 'SYSTEM', 'SYSMAN', 'DMSYS', 'OLAPSYS',
'XDB', 'EXFSYS', 'CTXSYS', 'WMSYS', 'DBSNMP',
'ORDSYS', 'OUTLN', 'TSMSYS', 'MDSYS')
and last_analyzed is null;
begin
dbms_output.enable(1000000);
----flush the monitorring information into the dba_tab_modifications
DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
----display the unanalyzed table--------------
dbms_output.put_line('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -');
dbms_output.put_line('Unalalyzed tables:');
for v_null in nullmonitor loop
dbms_output.put_line(v_null.owner || '.' || v_null.table_name ||
' has not been analyzed, consider gathering statistics');
end loop;
----display the information-------------------
dbms_output.put_line('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -' );
dbms_output.put_line('Over the Change_Rate 10%:');
for v_topinsert in overchangerate loop
dbms_output.put_line(v_topinsert.table_owner || '.' || v_topinsert.table_name || ' once has ' || v_topinsert.num_rows || ' rows, ' ||
'till now inserted ' || v_topinsert.inserts || ' rows, updated ' || v_topinsert.updates || ' rows, deleted ' || v_topinsert.deletes ||
' rows. consider gathering statistics');
end loop;
dbms_output.put_line('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -');
end;
/
下面的是分區表
set serveroutput on
declare
-----select OVER THE Change RATE TABLES---------------
cursor overchangerate is
select a.table_owner,a.table_name,a.partition_name,sum(a.inserts) inserts,sum(a.updates) updates,sum(a.deletes) deletes,sum(b.num_rows) num_rows
from dba_tab_modifications a,dba_tab_partitions b where a.table_owner =b.table_owner and a.table_name=b.table_name
and a.partition_name=b.partition_name and a.table_owner not in ('SYS', 'SYSTEM', 'SYSMAN', 'DMSYS', 'OLAPSYS', 'XDB',
'EXFSYS', 'CTXSYS', 'WMSYS', 'DBSNMP', 'ORDSYS','OUTLN', 'TSMSYS', 'MDSYS')
group by a.table_owner,a.table_name,a.partition_name
having (sum(a.inserts)/decode(sum(b.num_rows),0,1,sum(b.num_rows)))>=0.1
or
(sum(a.updates)/decode(sum(b.num_rows),0,1,sum(b.num_rows)))>=0.1
or
(sum(a.deletes)/decode(sum(b.num_rows),0,1,sum(b.num_rows)))>=0.1
order by a.table_name;
begin
dbms_output.enable(1000000);
----flush the monitorring information into the dba_tab_modifications
DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO;
----display the top_n_insert information-------------------
dbms_output.put_line('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -' );
dbms_output.put_line('Over the Change_Rate 10%:');
for v_topinsert in overchangerate loop
dbms_output.put_line(v_topinsert.table_owner || '.' || v_topinsert.table_name || ' partition ' || v_topinsert.partition_name || ' once has ' || v_topinsert.num_rows || ' rows, ' ||
'till now inserted ' || v_topinsert.inserts || ' rows, updated ' || v_topinsert.updates || ' rows, deleted ' || v_topinsert.deletes ||
' rows. consider gathering statistics');
end loop;
dbms_output.put_line('- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -' );
end;
/
在Oracle的11g版本中提供了統計數據自動收集的功能。在部署安裝11g Oracle軟件過程當中,其中有一個步驟即是提示是否啓動這個功能(默認是啓用這個功能)。
一、查看自動收集統計信息的任務及狀態:
SQL> select client_name,status from dba_autotask_client; CLIENT_NAME STATUS ---------------------------------------------------------------- -------- auto optimizer stats collection ENABLED auto space advisor ENABLED sql tuning advisor DISABLED SQL>
二、禁止自動收集統計信息的任務
SQL> exec DBMS_AUTO_TASK_ADMIN.DISABLE(client_name => 'auto optimizer stats collection',operation => NULL,window_name => NULL); PL/SQL procedure successfully completed. SQL> select client_name,status from dba_autotask_client; CLIENT_NAME STATUS ---------------------------------------------------------------- -------- auto optimizer stats collection DISABLED auto space advisor ENABLED sql tuning advisor DISABLED SQL>
三、啓用自動收集統計信息的任務
SQL> exec DBMS_AUTO_TASK_ADMIN.ENABLE(client_name => 'auto optimizer stats collection',operation => NULL,window_name => NULL); PL/SQL procedure successfully completed. SQL> select client_name,status from dba_autotask_client; CLIENT_NAME STATUS ---------------------------------------------------------------- -------- auto optimizer stats collection ENABLED auto space advisor ENABLED sql tuning advisor DISABLED SQL>
四、得到當前自動收集統計信息的執行時間:
SQL> col WINDOW_NAME format a20 SQL> col REPEAT_INTERVAL format a70 SQL> col DURATION format a20 SQL> set line 180 SQL> select t1.window_name,t1.repeat_interval,t1.duration 2 from dba_scheduler_windows t1,dba_scheduler_wingroup_members t2 3 where t1.window_name=t2.window_name and t2.window_group_name in ('MAINTENANCE_WINDOW_GROUP','BSLN_MAINTAIN_STATS_SCHED'); WINDOW_NAME REPEAT_INTERVAL DURATION -------------------- ---------------------------------------------------------------------- -------------------- WEDNESDAY_WINDOW freq=daily;byday=WED;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 THURSDAY_WINDOW freq=daily;byday=THU;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 SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0 +000 20:00:00 MONDAY_WINDOW freq=daily;byday=MON;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 7 rows selected. SQL>
其中:WINDOW_NAME:任務名 REPEAT_INTERVAL:任務重複間隔時間 DURATION:持續時間
5.修改統計信息執行的時間:
1.中止任務: SQL> BEGIN 2 DBMS_SCHEDULER.DISABLE( 3 name => '"SYS"."THURSDAY_WINDOW"', 4 force => TRUE); --中止任務是true 5 END; 6 / SQL> 2.修改任務的持續時間,單位是分鐘: SQL> BEGIN 2 DBMS_SCHEDULER.SET_ATTRIBUTE( 3 name => '"SYS"."THURSDAY_WINDOW"', 4 attribute => 'DURATION', 5 value => numtodsinterval(60,'minute')); 6 END; 7 / SQL> 3.開始執行時間,BYHOUR=2,表示2點開始執行: SQL> BEGIN 2 DBMS_SCHEDULER.SET_ATTRIBUTE( 3 name => '"SYS"."THURSDAY_WINDOW"', 4 attribute => 'REPEAT_INTERVAL', 5 value => 'freq=daily;byday=THU;byhour=10;byminute=40;bysecond=0'); 6 END; 7 / SQL> 4.開啓任務: SQL> BEGIN 2 DBMS_SCHEDULER.ENABLE( 3 name => '"SYS"."THURSDAY_WINDOW"'); 4 END; 5 / SQL> 5.查看修改後的狀況: SQL> select t1.window_name,t1.repeat_interval,t1.duration 2 from dba_scheduler_windows t1,dba_scheduler_wingroup_members t2 3 where t1.window_name=t2.window_name and t2.window_group_name in ('MAINTENANCE_WINDOW_GROUP','BSLN_MAINTAIN_STATS_SCHED'); WINDOW_NAME REPEAT_INTERVAL DURATION -------------------- ---------------------------------------------------------------------- -------------------- WEDNESDAY_WINDOW freq=daily;byday=WED;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 THURSDAY_WINDOW freq=daily;byday=THU;byhour=10;byminute=40;bysecond=0 +000 01:00:00 TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0 +000 04:00:00 SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0 +000 20:00:00 MONDAY_WINDOW freq=daily;byday=MON;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 SQL>
6.查看統計信息執行的歷史記錄
--維護窗口組 select * from dba_scheduler_window_groups; --維護窗口組對應窗口 select * from dba_scheduler_wingroup_members --維護窗口歷史信息 select* from dba_scheduler_windows --查詢自動收集任務正在執行的job select * from DBA_AUTOTASK_CLIENT_JOB; --查詢自動收集任務歷史執行狀態 select * from DBA_AUTOTASK_JOB_HISTORY; select * from DBA_AUTOTASK_CLIENT_HISTORY;
從10g開始,Oracle在建庫後就默認建立了一個名爲GATHER_STATS_JOB的定時任務,用於自動收集CBO的統計信息。這個自動任務默認狀況下在工做日晚上10:00-6:00和週末全天開啓。
一、查看自動收集統計信息的任務及狀態:
SQL> select job_name,schedule_name,enabled,last_start_date,last_run_duration,next_run_date 2 from dba_scheduler_jobs a 3 where job_name = 'GATHER_STATS_JOB'
二、啓用/禁止自動收集統計信息的任務
方法一: exec dbms_scheduler.disable('SYS.GATHER_STATS_JOB'); exec dbms_scheduler.enable('SYS.GATHER_STATS_JOB'); 方法二: alter system set "_optimizer_autostats_job"=false scope=spfile; alter system set "_optimizer_autostats_job"=true scope=spfile;
三、得到當前自動收集統計信息的執行時間
SQL> col WINDOW_NAME format a20 SQL> col DURATION format a20 SQL> col REPEAT_INTERVAL format a75 SQL> select t2.window_group_name,t1.window_name,t1.repeat_interval,t1.duration 2 from dba_scheduler_windows t1,dba_scheduler_wingroup_members t2 3 where t1.window_name=t2.window_name; WINDOW_GROUP_NAME WINDOW_NAME REPEAT_INTERVAL DURATION ------------------------------ -------------------- --------------------------------------------------------------------------- -------------------- MAINTENANCE_WINDOW_GROUP WEEKNIGHT_WINDOW freq=daily;byday=MON,TUE,WED,THU,FRI;byhour=22;byminute=0; bysecond=0 +000 08:00:00 MAINTENANCE_WINDOW_GROUP WEEKEND_WINDOW freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0 +002 00:00:00 SQL>
四、修改統計信息執行的時間
--修改WEEKEND_WINDOW的配置 (改爲和WEEKNIGHT_WINDOW相同,即週一~週五,每日的22:00向後8小時,至第二天凌晨6點) begin dbms_scheduler.set_attribute('WEEKEND_WINDOW','REPEAT_INTERVAL','freq=daily;byday=SAT,SUN;byhour=22;byminute=0;bysecond=0'); dbms_scheduler.set_attribute('WEEKEND_WINDOW','DURATION','+000 08:00:00'); end; / --若要還原成之前默認設置,可執行以下 --週末兩天都是全天: begin dbms_scheduler.set_attribute('WEEKEND_WINDOW','REPEAT_INTERVAL','freq=daily;byday=SAT;byhour=0;byminute=0;bysecond=0'); dbms_scheduler.set_attribute('WEEKEND_WINDOW','DURATION','+002 00:00:00'); end; /
五、查看統計信息執行的歷史記錄
--JOB運行歷史記錄 select * from dba_scheduler_job_log where job_name = 'GATHER_STATS_JOB' --正在運行的job select * from dba_scheduler_running_jobs