文章目錄
一.什麼是統計信息
統計信息主要是描述數據庫中表,索引的大小,規模,數據分佈狀況等的一類信息。例如,表的行數,塊數,平均每行的大小,索引的leaf blocks,索引字段的行數,不同值的大小等,都屬於統計信息。CBO正是根據這些統計信息數據,計算出不同訪問路徑下,不同join 方式下,各種計劃的成本,最後選擇出成本最小的計劃。
統計信息是存放在數據字典表中的,如tab$,一般可通過察看某些視圖來獲取統計信息狀況,如DBA_TABLES,DBA_INDEXES,DBA_TAB_COL_STATISTICS, DBA_TAB_HISTOGRAMS等。在這些視圖中包含表示統計信息的一些字段,這些字段只有蒐集過統計信息之後纔有值,否則是空的。例如,last_analyzed 字段表示上次統計信息蒐集的時間,可以根據這個字段,快速的瞭解最近一次統計信息蒐集的時間。
二.使用dbms_stats收集統計信息
DBMS_STATS包,主要提供了蒐集(gather),刪除(delete),導出(export),導入(import),修改(set),查看(get)統計信息的方法。
1.收集統計信息
-
收集全庫的統計信息
BEGIN dbms_stats.gather_database_stats( estimate_percent => dbms_stats.AUTO_SAMPLE_SIZE, method_opt => 'for all indexed columns', options => 'GATHER AUTO', cascade => FALSE); END; /
-
estimate_percent:採樣的百分比,使用dbms_stats.auto_sample_size選項允許Oracle自動估算要採樣的一個segment的最佳百分比。
-
method_opt選項適合在表和索引數據發生變化時刷新統計數據:
-
for table:只統計表
-
for all indexed columns:只統計有索引的表列
-
for all indexes:只分析統計相關索引
-
for all columns:分析所有的列
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’
(1).skewonly選項會耗費大量處理時間,因爲它要檢查每個索引中的每個列的值的分佈情況。如果dbms_stat發現一個索引的各個列分佈得不均勻,那麼就會爲該索引創建直方圖,幫助基於成本的SQL優化器決定是進行索引訪問,還是進行全表掃描訪問。
(2).repeat選項在重新分析任務所消耗的資源就會少一些。使用repeat選項時,只會爲現有的直方圖重新分析索引,不再搜索其他直方圖機會。定期重新分析統計數據時,應該採取這種方式。
(3).auto選項根據數據分佈以及應用程序訪問列的方式來創建直方圖。
-
options控制Oracle統計信息的刷新方式:
-
gather:重新分析整個架構
-
gather empty:只分析目前還沒有統計的表
-
gather stale:只重新分析修改量超過10%的表(包括插入、更新和刪除)
-
gather auto:重新分析當前沒有統計的對象,以及統計數據過期(變髒)的對象。使用gather auto類似於組合使用gather stale和gather empty[建議採用]
-
-
cascasde:是否級聯分析索引,默認爲false
-
-
收集schema統計信息
BEGIN dbms_stats.gather_schema_stats( ownname => 'DSG', options => 'GATHER AUTO', estimate_percent => dbms_stats.AUTO_SAMPLE_SIZE, method_opt => 'for all indexed columns', cascade => FALSE); END; /
-
收集單表的統計信息
BEGIN dbms_stats.gather_table_stats( ownname => 'DSG', tabname => 'T1', estimate_percent => dbms_stats.AUTO_SAMPLE_SIZE, method_opt => 'for all indexed columns', cascade => FALSE); END; /
dbms_stats.gather_table_stats(
owner VARCHAR2,
tablename VARCHAR2,
partname VARCHAR2,
estimate_percent NUMBER,
block_sample BOOLEAN,
method_opt VARCHAR2,
degree NUMBER,
granularity VARCHAR2,
cascade BOOLEAN,
stattab VARCHAR2,
statid VARCHAR2,
statown VARCHAR2,
no_invalidate BOOLEAN,
force BOOLEAN
)
參數說明:
1.owner:要分析表的所有者
2.tablename:要分析的表的表名
3.partname:分區名
4.estimate_percent:採樣行的百分比,從0.000001-100,null爲全部分析,不採樣。DBMS_STATS.AUTO_SAMPLE_SIZE是默認值,由Oracle決定最佳採樣率。
5.block_sample:是否用塊採樣代替行採樣。
6.method_opt:決定histograms信息是怎樣被統計的,method_opt的取值如下:
- for all columns:統計所有的histograms
- for all indexed columns:統計所有index列的histograms
- for all hidden coloumns:統計hidden列的histograms
- for columns SIZE | REPEAT | AUTO | SKEWONLY 統計指定列的histograms,N的取值範圍是0-254
7.degree:設置統計信息收集的並行度,默認值爲null。
8.cascade:收集索引的統計信息,默認爲false
9.stattab:指定存儲統計信息的表。
10.statid:如果多個表的統計信息存儲在一個stattab中時,statid用作分區條件。
11.statown:存儲統計信息表的所有着。如果不指定上述三個參數,則統計信息會被更新到數據字典。
12.force:即使表鎖住了也收集統計信息。
2.直方圖
在Oracle中直方圖是一種對數據分佈質量情況進行描述的工具。它會按照某一列不同值出現數量多少,以及出現的頻率高低來繪製數據的分佈情況,以便能夠指導優化器根據數據的分佈做出正確的選擇。在某些情況下,表的列中的數值分佈將會影響優化器使用索引還是執行全表掃描的決策。當 where 子句的值具有不成比例數量的數值時,將出現這種情況,使得全表掃描比索引訪問的成本更低。這種情況下如果where 子句的過濾謂詞列之上上有一個合理的正確的直方圖,將會對優化器做出正確的選擇發揮巨大的作用,使得SQL語句執行成本最低從而提升性能。
-
oracle中使用直方圖的場景
在分析表或索引時,直方圖用於記錄數據的分佈。通過獲得該信息,基於成本的優 化器就可以決定使用將返回少量行的索引,而避免使用基於限制條件返回許多行的索引。直方圖的使用不受索引的限制,可以在表的任何列上構建直方圖。
構造直方圖最主要的原因就是幫助優化器在表中數據嚴重偏斜時做出更好的規劃:例如,如果一到兩個值構成了表中的大部分數據(數據偏斜),相關的索引就可能無法幫助減少滿足查詢所需的I/O數量。創建直方圖可以讓基於成本的優化器知道何時使用索引才最合適,或何時應該根據WHERE子句中的值返回表中80%的記錄。
通常情況下在以下場合中建議使用直方圖:
(1)、當Where子句引用了列值分佈存在明顯偏差的列時:當這種偏差相當明顯時,以至於 WHERE 子句中的值將會使優化器選擇不同的執行計劃。這時應該使用直方圖來幫助優化器來修正執行路徑。(注意:如果查詢不引用該列,則創建直方圖沒有意義。這種錯誤很常見,許多 DBA 會在偏差列上創建柱狀圖,即使沒有任何查詢引用該列。)
(2)、當列值導致不正確的判斷時:這種情況通常會發生在多表連接時,例如,假設我們有一個五項的表聯接,其結果集只有 10 行。Oracle 將會以一種使第一個聯接的結果集(集合基數)儘可能小的方式將表聯接起來。通過在中間結果集中攜帶更少的負載,查詢將會運行得更快。爲了使中間結果最小化,優化器嘗試在 SQL 執行的分析階段評估每個結果集的集合基數。在偏差的列上擁有直方圖將會極大地幫助優化器作出正確的決策。如優化器對中間結果集的大小作出不正確的判斷,它可能會選擇一種未達到最優化的表聯接方法。因此向該列添加直方圖經常會向優化器提供使用最佳聯接方法所需的信息。
-
如何收集直方圖
使用dbms_stata.gather_table_stats來收集統計信息是生成直方圖是由參數method_opt來控制的method_opt參數的語法是由多個部分組成的.前兩個部分是強制性的:
FOR ALL [INDEXED | HIDDEN] COLUMNS [size_clause]
FOR COLUMNS [size clause] column [size_clause] [,column…]method_opt語法中的主要部分控制哪些列將收集列的統計信息(min,max,ndv,nulls).缺省是for all columns,它將會對錶中所有的列(包括隱藏列)收集基本的列統計信息.
for all indexed columns將只對哪些包含索引的列進收集列統計信息.
for all hidden columns將只會對哪些虛擬列收集列統計信息.這意味着在對錶收集統計時真實列是不會生成列統計信息的.這個值不能用於通常的統計信息收集.它只能用在當基表列的統計信息精確收集後在表中創建新的虛擬列.然後對新的虛擬列收集列統計信息時才使用它.
注意如果列不在統計信息收集列表中那麼只會收集列的平均長度.
size用來指定直方圖的桶數SIZE {integer | REPEAT | AUTO | SKEWONLY}
auto:基於列的使用信息(sys.col_usage$)和是否存在數據傾斜來收集直方圖
integer:人爲的指定創建直方圖的桶數範圍是1到254,如果size 1意味着不創建直方圖
repeat:只會對已經存在直方圖的列重新生成直方圖.如果是一個分區表,repeat會確保對在全局級別存在直方圖的列重新生成直方圖.這是不被推薦的設置的.當前直方圖的桶數將會作爲重新生成直方圖所使用的桶數的最大值.比如,當前直方圖的桶數是5,那麼生成的直方圖最大桶數就是5,說的直白點就是刷新現有直方圖的列上的統計信息.
skewonly:對任何數據分佈出現傾斜列的自動創建直方圖示例:
收集統計信息,但是不收集直方圖
exec dbms_stats.gather_table_stats('DSG','T1',METHOD_OPT=>'for all columns size 1');
收集統計信息,並且對t1表的flag列收集直方圖
exec dbms_stats.gather_table_stats('DSG','T1',METHOD_OPT=>'for columns flag size skewonly');
收集統計信息,並且收集所有列直方圖
exec dbms_stats.gather_table_stats('DSG','T1',METHOD_OPT=>'for all columns size skewonly');
3.修改/查看統計信息參數
可以使用USE_STALE_PERCENT參數來指定統計信息的陳舊百分比爲其它值.該值的閾值默認值爲10%,但是可以重寫,這樣在行改變的百分比沒有達到指定的閾值錢,統計信息不會被標記爲陳舊
exec dbms_stats.set_database_prefs('STALE_PERCENT','25');
查詢當前數據庫的STALE_PERCENT值:
select dbms_stats.get_prefs('STALE_PERCENT') FROM DUAL;
select dbms_stats.get_prefs('STALE_PERCENT','DSG','T1') from dual;
4.刪除統計信息
例如刪除表統計信息
exec dbms_stats.delete_table_stats('DSG','T1');
5.導出導入統計信息
# 1.創建統計信息歷史保留表
exec dbms_stats.create_stat_table(
ownname => '',
stattab => ''
)
# 2.導出整個scheme的統計信息
exec dbms_stats.export_schema_stats(
ownname => '',
stattab => ''
)
# 3.分析scheme
Exec dbms_stats.gather_schema_stats(
ownname => '',
options => 'GATHER AUTO',
estimate_percent => dbms_stats.auto_sample_size,
method_opt => 'for all indexed columns ',
degree => 6
)
# 4.分析表
exec dbms_stats.gather_table_stats(
ownname => '',
tabname =>'',
estimate_percent => 10,
method_opt=> 'for all indexed columns'
)
# 5.分析索引
exec dbms_stats.gather_index_stats(
ownname => '',
indname => '',
estimate_percent => 10,
degree => 6
)
# 6.如果發現執行計劃走錯,刪除表的統計信息
exec dbms_stats.delete_table_stats(
ownname => '',
tabname => ''
)
# 7.導入錶的歷史統計信息
exec dbms_stats.import_table_stats(
ownname => '',
tabname => '',
stattab => '')
6.其它常用功能
分析數據庫(包括所有的用戶對象和系統對象):gather_database_stats
分析用戶所有的對象(包括表、索引、簇):gather_schema_stats
分析表:gather_table_stats
分析索引:gather_index_stats
刪除數據庫統計信息:delete_database_stats
刪除用戶方案統計信息:delete_schema_stats
刪除表統計信息:delete_table_stats
刪除索引統計信息:delete_index_stats
刪除列統計信息:delete_column_stats
設置表統計信息:set_table_stats
設置索引統計信息:set_index_stats
設置列統計信息:set_column_stats
7.自動收集統計信息
oracle11g默認啓用自動收集統計信息,當統計信息別標記爲過期(行的變化百分比超過USE_STALE_PERCENT設置的閾值),那麼就會在自動任務窗口中進行統計信息的收集.
首先查看scheduler program
oracle通過調度program來進行自動的收集統計信息:
SQL> select owner,program_name,program_action,enabled from dba_scheduler_programs where program_name='GATHER_STATS_PROG';
OWNER PROGRAM_NAME PROGRAM_ACTION ENABL
------------------------------ ------------------------------ -------------------------------------------------- -----
SYS GATHER_STATS_PROG dbms_stats.gather_database_stats_job_proc TRUE
執行的是dbms_stats.gather_database_stats_job_proc存儲過程
查詢自動收集統計信息的任務:
SELECT client_name, task_name, status
FROM dba_autotask_task
WHERE client_name = 'auto optimizer stats collection';
CLIENT_NAME TASK_NAME STATUS
----------------------- ----------------- ------------------------------ --------
auto optimizer stats collection gather_stats_prog ENABLED
查詢自動任務客戶端是否啓用
SQL> SELECT CLIENT_NAME, STATUS
FROM DBA_AUTOTASK_CLIENT
WHERE CLIENT_NAME = 'auto optimizer stats collection';
CLIENT_NAME STATUS
---------------------------------------- --------
auto optimizer stats collection ENABLED
查詢自動任務的頻率
col REPEAT_INTERVAL for a60
col DURATION for a30
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';
WINDOW_NAME REPEAT_INTERVAL DURATION ENABL
------------------------------ ------------------------------------------------------------ ------------------------------ -----
MONDAY_WINDOW freq=daily;byday=MON;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE
TUESDAY_WINDOW freq=daily;byday=TUE;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE
WEDNESDAY_WINDOW freq=daily;byday=WED;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE
THURSDAY_WINDOW freq=daily;byday=THU;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE
FRIDAY_WINDOW freq=daily;byday=FRI;byhour=22;byminute=0; bysecond=0 +000 04:00:00 TRUE
SATURDAY_WINDOW freq=daily;byday=SAT;byhour=6;byminute=0; bysecond=0 +000 20:00:00 TRUE
SUNDAY_WINDOW freq=daily;byday=SUN;byhour=6;byminute=0; bysecond=0 +000 20:00:00 TRUE
可以看到週一到週五每天的22:00開始,持續4小時,週六週日,6點開始,執行20小時.
-
啓用自動收集
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;
查詢自動任務客戶端:
SQL> select client_name,status from dba_autotask_client; CLIENT_NAME STATUS ---------------------------------------- -------- auto optimizer stats collection DISABLED auto space advisor ENABLED sql tuning advisor ENABLED
-
關閉某個單獨的時間調度窗口
BEGIN DBMS_AUTO_TASK_ADMIN.disable(client_name => 'auto optimizer stats collection', operation => NULL, window_name => 'MONDAY_WINDOW'); END; /
查詢窗口調度, 驗證關閉情況,如下,optimizer_stats列爲DISABLED
SQL> 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; WINDOW_NAME WINDOW_NEXT_TIME WINDO OPTIMIZE ------------------------------ --------------------------------------------------------------------------- ----- -------- MONDAY_WINDOW 18-NOV-19 10.00.00.000000 PM PRC FALSE DISABLED
4.關閉所有的窗口調度
BEGIN DBMS_AUTO_TASK_ADMIN.disable ( client_name => 'auto optimizer stats collection', operation => NULL, window_name => NULL); END; /
5.修改窗口屬性
修改任務的持續時間,單位是分鐘 BEGIN DBMS_SCHEDULER.SET_ATTRIBUTE( name=>'"SYS"."FRIDAY_WINDOW"', attribute=>'DURATION', value=>numtodsinterval(180, 'minute')); END; 修改開始執行時間,BYHOUR=2,表示2點開始執行 BEGIN DBMS_SCHEDULER.SET_ATTRIBUTE( name=>'"SYS"."FRIDAY_WINDOW"', attribute=>'REPEAT_INTERVAL', value=>'FREQ=WEEKLY;BYDAY=MON;BYHOUR=2;BYMINUTE=0;BYSECOND=0'); END;
三.統計信息常用數據字典
- DBA_TABLES
- DBA_TAB_STATISTICS
- DBA_TAB_COL_STATISTICS
- DBA_TAB_HISTOGRAMS
- DBA_IND_STATISTICS