四、統計信息

 

一、什麼是統計信息?sql

統計信息就是數據庫的偵察兵,記錄了表和表中一些列的一些信息,通常SQL指定執行計劃的時候都要先看錶的統計信息,以決定執行計劃的選擇。數據庫

 

表的統計信息通常在dba_tables中,表中列的統計信息通常在dba_tab_col_statisticssession

 

select table_name,column_name,num_distinct,num_nulls,last_analyzed,avg_col_len,histogram from dba_tab_col_statistics where table_name='TEST';oracle

 

沒有收集統計系信息以前,dba_tables中記錄的關於表的 num_rows和blocks都是空的。  dba_tab_col_statistics中是沒有列的記錄的。咱們來看一下手機完統計信息的狀態。ui

 select table_name,column_name,num_distinct,num_nulls,last_analyzed,avg_col_len,histogram from dba_tab_col_statistics where table_name='TEST';spa

 

收集統計信息的過程:code

一、將表有多少行,表中有多少個block  計算出來,記錄到dba_tables中。(select count(*) from test;   select SEGMENT_NAME,blocks from dba_segments where segment_name='TEST'; )orm

二、計算表中每一個列的基數,null值,平均的行長度等,記錄到基表中。blog

 

採樣率:索引

一個表是由塊組成的,若是採樣率不是100%有些塊就會收集不到。若是採樣率設置成30%,就會隨機的抽取表中30%的塊,進行統計信息的收集。

小表基本都是100%收集的。

通常經驗:   <1G   100%    1-5G    50%    5-10G    30%      >10G通常爲分區表了,老分區的數據通常是不會變的, 最新一個區的數據纔會變化,因此通常是已分區爲粒度來收集的。

(estimate_persent => 100)控制,若是不指定採樣比,oracle會自動選擇採樣率,也是默認的選項,最後使用默認。

 

收集直方圖與否:

method_opt => for all columns size 1    不收集直方圖

method_opt => for all columns size skewonly     收集直方圖  (沒收集直方圖以前histogram是none,num_bucket是0)  

    自動收集直方圖時,Oracle對直方圖的選擇, FREQUENCY ----頻率直方圖(基數小於254時使用) HEIGHT  BALANCED ------  等高直方圖(基數大於254時使用)       NONE  distinct值=行數     或者distinct值爲0的時候不收集

    生產中不能夠使用這個選項,由於表咱們只對where中的列和基數很低的列收集。。這個選項會收集全部列的

method_opt => for all columns size auto       這個是10g、11g、12c中收集統計信息的默認選項,自動根據where條件中的信息對列有選擇性的收直方圖(只收集出如今where條件中而且基數很低的列)。也是官方推薦的方式

Oracle怎麼判斷哪些列在where條件中呢?

begin dbms_stats.flush_database_monitoring_info;end;--將內存中的統計數據刷出去【這個在生產上也能夠隨便刷,就是將內存中的數據刷到磁盤上,這個數據很是小,不會刷死庫的】
(默認是由smon刷的,15min一次)

select 
r.name owner,
o.name table_name,
c.name column_name,
equality_preds,----等值過濾的次數
equijoin_preds,----等值過濾join,好比where a.id=b.in
range_preds,----範圍過濾,好比><and,between
like_preds,----like過濾
null_preds,----null過濾
timestamp
from sys.col_usage$ u,sys.obj$ o,sys.col$ c,sys.user$ r
where
o.obj# = u.obj# and
c.obj# = u.obj# and
c.col# = u.intcol# and
r.name = 'SCOTT' and
o.name = 'TEST';

auto也不是萬能的,好比  有些時候生產上的where條件是沒有某些列的,可是咱們私底下sqlplus查詢時候查過這些列,也會致使這些列被auto收集。

method_opt => for all columns size repeat    延續上一次收集的方法,以前怎麼收集的,此次還怎麼收集 

method_opt => for columns owner size auto    只針對owner列收集直方圖   (下次若是是for all columns size repeat 仍是隻對owner收集直方圖)

method_opt = > for columns owner,subobject_name size auto  對owner和subobject_name兩列收集直方圖(若是肯定了哪些列要收集直方圖,之後每次收集的時候都肯定也能夠不用repeat)

 

通常去新公司工做的時候用repeat    (其實11g後用auto也能夠)

新系統上線的時候用 1,不收集直方圖,對跑得慢的列再收直方圖,長此以往這個系統就穩定了

 

統計信息知識總結:

一、如何查看已收集了統計信息的一個表的採樣率:

select 
  owner,table_name,num_rows,sample_size,
  ceil(sample_size/num_rows*100) estimate_percent
from dba_tab_statistics
where owner = 'SCOTT' and table_name = 'TEST';

 

 

二、收集統計信息:

begin
    dbms_stats.gather_table_stats(
    ownname=>'SCOTT',
    tabname=>'TEST',
    estimate_percent=>30,
    method_opt=>'for all columns size auto',
    no_invalidate=>FALSE,
    degree=>1,
    cascade=>true);
end;
/

 

三、收集完統計信息後,隔多久再收集一次?

3.1看統計信息是否過時。過時就須要收集。

判斷統計信息是否過時:

begin
dbms_stats.flush_database_monitoring_info;
end;
/
select 
owner,table_name name,object_type,stale_stats,
last_analyzed from dba_tab_statistics
where table_name in ('TEST')
and owner = 'SCOTT'
and (stale_stats = 'YES' or last_analyzed is null);

stale_stats爲 no 就是沒有過時,yes 就是過時了。

一個表有超過10%的數據變化,統計信息就會過時

 

3.2 怎麼判斷統計信息是由於什麼過時的。

alter session set nls_date_format='yyyymmdd hh24:mi:ss';
col owner for a15 col table_name for a15 col partition_name for a20 col subpartition_name for a20 select * from ( select * from ( select * from ( select u.name owner,o.name table_name, null partition_name, null subpartition_name, m.inserts,m.updates,m.deletes,m.timestamp, decode(bitand(m.flags,1),1,'YES','NO') truncated, m.drop_segments from sys.mon_mods_all$ m, sys.obj$ o,sys.tab$ t,sys.user$ u where o.obj# = m.obj# and o.obj#=t.obj# and o.owner# = u.user# union all select u.name,o.name,o.subname,null, m.inserts,m.updates,m.deletes,m.timestamp, decode(bitand(m.flags,1),1,'YES','NO'), m.drop_segments from sys.mon_mods_all$ m,sys.obj$ o,sys.user$ u where o.owner#=u.user# and o.obj#=m.obj# and o.type#=19 union all select u.name,o.name,o2.subname,o.subname, m.inserts,m.updates,m.deletes,m.timestamp, decode(bitand(m.flags,1),1,'YES','NO'), m.drop_segments from sys.mon_mods_all$ m,sys.obj$ o,sys.tabsubpart$ tsp,sys.obj$ o2, sys.user$ u where o.obj#=m.obj# and o.owner#=u.user# and o.obj# = tsp.obj# and o2.obj#=tsp.pobj# ) where owner not like '%SYS%' and owner not like 'XDB' union all select * from ( select u.name owner,o.name table_name,null partition_name, null subpartition_name, m.inserts,m.updates,m.deletes,m.timestamp, decode(bitand(m.flags,1),1,'YES','NO') truncated, m.drop_segments from sys.mon_mods$ m,sys.obj$ o,sys.tab$ t,sys.user$ u where o.obj#=m.obj# and o.obj#=t.obj# and o.owner#=u.user# union all select u.name,o.name,o.subname,null, m.inserts,m.updates,m.deletes,m.timestamp, decode(bitand(m.flags,1),1,'YES','NO'), m.drop_segments from sys.mon_mods$ m,sys.obj$ o,sys.user$ u where o.owner#=u.user# and o.obj#=m.obj# and o.type#=19 union all select u.name,o.name,o2.subname,o.subname, m.inserts,m.updates,m.deletes,m.timestamp, decode(bitand(m.flags,1),1,'YES','NO'), m.drop_segments from sys.mon_mods$ m,sys.obj$ o,sys.tabsubpart$ tsp,sys.obj$ o2, sys.user$ u where o.obj#=m.obj# and o.owner#=u.user# and o.obj# = tsp.obj# and o2.obj#=tsp.pobj# ) where owner not like '%SYS%' and owner not like '%XDB%' ) order by inserts desc ) where rownum<50;

該語句查詢的是 最近一次收集統計信息後,到如今爲止表數據量的變化。

該腳本能夠用來監控系統中核心表的dml,也能夠判斷高水位線是否須要回收、索引是否須要重建,等等。

 

3.3 數據庫有一個自動的job天天晚上自動收集統計信息。

AUTOTASK只收集變化量超過10%的表

若是有但願的計劃任務,最好用OS的crontab不要用scheduler,scheduler會死,可是crontab不會

數據庫自帶的job收集統計信息是很差的,由於頗有可能收集不完。

最好把db自帶的收集統計信息的job停掉,而後本身定製收集方案。

相關文章
相關標籤/搜索