您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么理解Oracle統(tǒng)計(jì)信息”,在日常操作中,相信很多人在怎么理解Oracle統(tǒng)計(jì)信息問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”怎么理解Oracle統(tǒng)計(jì)信息”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!
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 ) 參數(shù)說(shuō)明 |
1.owner:要分析表的所有者 2.tablename:要分析的表的表名 3.partname:分區(qū)名 4.estimate_percent:采樣行的百分比,從0.000001-100,null為全部分析,不采樣。常量DBMS_STATS.AUTO_SAMPLE_SIZE是默認(rèn)值,由Oracle決定最佳采樣率。 5.block_sample:是否用塊采樣代替行采樣。 6.method_opt:決定histograms信息是怎樣被統(tǒng)計(jì)的,method_opt的取值如下:
7.degree:設(shè)置統(tǒng)計(jì)信息收集的并行度,默認(rèn)值為null。 8.cascade:收集索引的統(tǒng)計(jì)信息,默認(rèn)為false 9.stattab:指定存儲(chǔ)統(tǒng)計(jì)信息的表。 10.statid:如果多個(gè)表的統(tǒng)計(jì)信息存儲(chǔ)在一個(gè)stattab中時(shí),statid用作分區(qū)條件。 11.statown:存儲(chǔ)統(tǒng)計(jì)信息表的所有著。 如果不指定上述三個(gè)參數(shù),則統(tǒng)計(jì)信息會(huì)被更新到數(shù)據(jù)字典。 12.force:即使表鎖住了也收集統(tǒng)計(jì)信息。 |
BEGIN DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', tabname => 'DEPT', estimate_percent => 30, method_opt => 'for all columns size repeat', no_invalidate => FALSE, degree => 8, cascade => TRUE); END; / |
BEGIN DBMS_STATS.GATHER_TABLE_STATS(ownname => 'ROBINSON', tabname => 'P_TEST', estimate_percent => 30, method_opt => 'for all columns size repeat', no_invalidate => FALSE, degree => 8, granularity => 'ALL', cascade => TRUE); END; / |
注意:分區(qū)的統(tǒng)計(jì)信息合并 到 DBA_TABLES
estimate_percent
表示采樣率,采樣率設(shè)置太大,也沒必要,使用dbms_stats.auto_sample_size選項(xiàng)允許Oracle自動(dòng)估算要采樣的一個(gè)segment的最佳百分比。
如果表非常大,采樣率過(guò)高會(huì)導(dǎo)致收集統(tǒng)計(jì)信息跑很長(zhǎng),增加了系統(tǒng)壓力。
采樣率設(shè)置過(guò)小,統(tǒng)計(jì)的信息就不能很完整的體現(xiàn)表中數(shù)據(jù)的分布,這樣CBO在進(jìn)行執(zhí)行計(jì)劃的選擇上,很可能選擇錯(cuò)誤的執(zhí)行計(jì)劃。
根據(jù)工作經(jīng)驗(yàn):
表小于1GB 采樣率可以設(shè)置50%-100%
表大于1GB小于5GB可以設(shè)置30%
表大于5GB 這類表都應(yīng)該進(jìn)行分區(qū),采樣率可以設(shè)置為30%
method_opt 有兩部分構(gòu)成
表示收集的方法,參數(shù)分為兩部分
這一部分for all [indexed | hidden] columns"
控制著哪些列將會(huì)收集列的基本統(tǒng)計(jì)信息(目標(biāo)列上的最小值, 最大值, 列上不同值的數(shù)量, 空值的數(shù)量等等). 系統(tǒng)默認(rèn)值為 for all columns, 它將收集表上所有列(包括隱藏列)的基本的統(tǒng)計(jì)信息. 此外, 它的其他可選值如下所示:
FOR ALL INDEXED COLUMNS 指定只有含有索引的字段才能收集列的基本統(tǒng)計(jì)信息. 一般不推薦使用這個(gè)選項(xiàng)值, 因?yàn)樵跀?shù)據(jù)庫(kù)環(huán)境中的所有 sql 語(yǔ)句所使用的字段, 比如 select 后面的字段, where 后面字段, group by 中的字段, 并不只是會(huì)引用含有索引的字段. |
FOR ALL HIDDEN COLUMNS 指定表中所有不可見的字段才能收集列的基本統(tǒng)計(jì)信息, 也就是說(shuō)不會(huì)去收集表上實(shí)際可見的列的統(tǒng)計(jì)信息. 同樣的一般也不推薦使用這個(gè)選項(xiàng)值. 這個(gè)選項(xiàng)值通常只用于這種情況, 在一個(gè)所有列的統(tǒng)計(jì)信息都是準(zhǔn)確的表中新增了一個(gè)或幾個(gè)不可見或者說(shuō)是虛擬的列, 只需要收集這個(gè)或者這幾個(gè)不可見列的統(tǒng)計(jì)信息, 而不再重復(fù)去其他列的統(tǒng)計(jì)信息, 那么就使用 for all hidden columns 這個(gè)選項(xiàng). |
第二部分"Size [size_clause]"
控制收集直方圖的方式, size 后面可以有以下選項(xiàng)
AUTO Oracle 自己決定根據(jù)列的統(tǒng)計(jì)信息(sys.col_usage$)以及列的數(shù)據(jù)傾斜程度(均勻分布程度)決定哪些列需要收集直方圖 Integer 指定收集直方圖的桶數(shù), 桶數(shù)最小為 1 最大為 254 (針對(duì) 11g 及以前的版本, 12c 后沒有這個(gè)限制).注意如果桶數(shù)為 1, 即 size 1 意味著不建立直方圖, 如果已經(jīng)有直方圖的列則會(huì)刪除該列的直方圖. REPEAT 只在已經(jīng)有直方圖的列上重新收集直方圖. repeat 會(huì)確保在全局級(jí)別上對(duì)已經(jīng)存在直方圖的列重新收集直方圖. 一般不推薦使用這個(gè)選項(xiàng), 因?yàn)樾碌闹狈綀D使用的桶數(shù)將不能超過(guò)舊的直方圖中的桶數(shù). 假設(shè)當(dāng)前直方圖中桶數(shù)為 5, 當(dāng)使用 size repeat 重新收集直方圖時(shí), 新的直方圖使用的桶數(shù)將不能超過(guò) 5 , 這鐘方式可能不會(huì)取得好的效果. SKEWONLY 只在數(shù)據(jù)不均勻分布的列上收集直方圖. 讓ORACLE 自己判斷列是否收集直方圖 只要是列傾斜了 ORACLE就會(huì)收集直方圖 OLTP系統(tǒng)用這個(gè) 非??拥?基本上所有列都要收集直方圖 |
如果 method_opt 的默認(rèn)參數(shù) for all columns size auto 在你的數(shù)據(jù)環(huán)境不適用, 可能你遇到的情況屬于下面兩種情況:
1.除了指定的列, 在其它列上創(chuàng)建直方圖
2.只在指定的列上創(chuàng)建直方圖
一個(gè)穩(wěn)定的系統(tǒng)收集統(tǒng)計(jì)信息的時(shí)候推薦使用method_opt=> 'for all columns size repeat',repeat表示以前收集過(guò)直方圖,現(xiàn)在收集統(tǒng)計(jì)信息的時(shí)候就收集直方圖,如果以前沒收集過(guò)直方圖,現(xiàn)在收集統(tǒng)計(jì)信息的時(shí)候就不收集。
有時(shí)候收集統(tǒng)計(jì)信息的時(shí)候,用method_opt => 'for all columns size auto',很有可能把當(dāng)前的sql搞定了,但是把其他的sql搞悲劇了,這是因?yàn)閍uto表示Oracle根據(jù)謂詞過(guò)濾信息(前文講解直方圖的時(shí)候提到過(guò)的where條件過(guò)濾),自動(dòng)判斷該列是否收集直方圖。一個(gè)穩(wěn)定的系統(tǒng),不應(yīng)該讓Oracle去自動(dòng)判斷,自動(dòng)判斷很可能就會(huì)出事,比如某列不該收集直方圖,設(shè)置auto過(guò)后它自己去收集直方圖了,從而導(dǎo)致系統(tǒng)不穩(wěn)定。
options
控制Oracle統(tǒng)計(jì)信息的刷新方式:
gather:重新分析整個(gè)架構(gòu)
gather empty:只分析目前還沒有統(tǒng)計(jì)的表
gather stale:只重新分析修改量超過(guò)10%的表(包括插入、更新和刪除)
gather auto:重新分析當(dāng)前沒有統(tǒng)計(jì)的對(duì)象,以及統(tǒng)計(jì)數(shù)據(jù)過(guò)期(變臟)的對(duì)象。使用gather auto類似于組合使用gather stale和gather empty
degree
表示收集統(tǒng)計(jì)信息的時(shí)候并行度,并行度根據(jù)你系統(tǒng)配置以及當(dāng)前系統(tǒng)可用資源自行設(shè)置。 一般degree設(shè)置4--8。一個(gè)CPU 一般可以開2個(gè)線程
DEGREE 就等于 show parameter cpu
你開并行8去收集統(tǒng)計(jì)信息,很有可能開 17個(gè)進(jìn)程 ,1個(gè)進(jìn)程作為主進(jìn)程來(lái)協(xié)調(diào)其他16個(gè)并行進(jìn)程,8個(gè)進(jìn)程 進(jìn)行 讀取數(shù)據(jù) 另外8個(gè)進(jìn)程 來(lái)進(jìn)行 CPU運(yùn)算 進(jìn)行分析
cascade
表示收集表的統(tǒng)計(jì)信息時(shí)候同時(shí)收集索引的統(tǒng)計(jì)信息。其實(shí)收集索引的統(tǒng)計(jì)信息非常坑爹, 因?yàn)樗饕占y(tǒng)計(jì)信息 是單塊讀。
no_invalidate
表示收集統(tǒng)計(jì)信息之后在共享池中引用了相關(guān)表的SQL游標(biāo)是否失效。這個(gè)一定要設(shè)置為FALSE,默認(rèn)是TRUE ,不然你可能在做SQL優(yōu)化的時(shí)候,你發(fā)現(xiàn)明明更新了統(tǒng)計(jì)信息,但是執(zhí)行計(jì)劃還是沒改變。
granularity
統(tǒng)計(jì)數(shù)據(jù)的收集,'ALL' - 收集所有(子分區(qū),分區(qū)和全局)統(tǒng)計(jì)信息
① ALL:采集Global、partition、subpartition等粒度統(tǒng)計(jì)信息。
② AUTO:根據(jù)分區(qū)類型,由Oracle確定統(tǒng)計(jì)信息采集粒度。
③ PARTITION:只采集partition粒度統(tǒng)計(jì)信息。
④ SUBPARTITION:只采集subpartition粒度統(tǒng)計(jì)信息
partname
分區(qū)表的某個(gè)分區(qū)名
exec dbms_stats.flush_database_monitoring_info; --刷新sys.col_usage$ 和視圖:sys.DBA_TAB_MODIFICATIONS select owner, table_name name, object_type, stale_stats, last_analyzed from dba_tab_statistics where table_name in (table_name) and owner = 'OWNER_NAME' and (stale_stats = 'YES' or last_analyzed is null); |
實(shí)驗(yàn)一查看統(tǒng)計(jì)信息是否過(guò)期
1.創(chuàng)建一個(gè)實(shí)驗(yàn)表 CREATE TABLE TEST AS SELECT * FROM DBA_OBJECTS; |
2.收集統(tǒng)計(jì)信息 BEGIN DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', tabname => 'TEST', estimate_percent => 100, method_opt => 'for all columns size auto', no_invalidate => FALSE, degree => 1, cascade => TRUE); END; / |
3.刷新 exec dbms_stats.flush_database_monitoring_info; |
4.查看test表的統(tǒng)計(jì)的信息是否過(guò)期,顯示空行表示沒有過(guò)期 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); -----結(jié)果空行----- |
5.刪除20%的數(shù)據(jù),讓統(tǒng)計(jì)信息過(guò)期 select count(*) from test; delete from test where rownum<=72388*0.2; |
6.再次刷新 exec dbms_stats.flush_database_monitoring_info; |
7.查看統(tǒng)計(jì)信息是否過(guò)期,有結(jié)果返回表示統(tǒng)計(jì)信息過(guò)期 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); OWNER NAME OBJECT_TYPE STA LAST_ANALYZED ------------------------------ ------------------------------ ------------ --- SCOTT TEST TABLE YES 2018-05-13 20:18:40 |
實(shí)驗(yàn)二 查看是什么操作讓統(tǒng)計(jì)信息過(guò)期的腳本
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; 可以發(fā)現(xiàn)是刪除導(dǎo)致統(tǒng)計(jì)信息過(guò)期 |
案列1 執(zhí)行大批量的update,立即手動(dòng)收集統(tǒng)計(jì)信息
我在10點(diǎn)收集了統(tǒng)計(jì)信息, 10點(diǎn) 過(guò)5分鐘執(zhí)行了 一個(gè) 大批量的 update操作 你在 10點(diǎn)10 執(zhí)行查詢,但是我發(fā)現(xiàn)查詢變慢了怎么辦? 也就是說(shuō),某個(gè)表會(huì)突然發(fā)生大批的DML操作怎么辦? |
解決方法:
收集統(tǒng)計(jì)信息的腳本直接放update后面,如果不立即收集
那肯定要?jiǎng)討B(tài)采樣,動(dòng)態(tài)采樣默認(rèn)是2 ,沒用
這種至少要LEVEL 達(dá)到6,才可能有效果
如果是偶爾性質(zhì)的,那么就要注意統(tǒng)計(jì)信息收集策略,當(dāng)他發(fā)生變化了就立即收集
如果是經(jīng)常性質(zhì)的,那么就在SQL里面加上動(dòng)態(tài)采樣的HINT
SELECT owner, table_name, num_rows, sample_size, trunc(sample_size / num_rows * 100) estimate_percent FROM DBA_TAB_STATISTICS WHERE owner='SCOTT' AND table_name='TEST';
|
實(shí)驗(yàn) size auto 的方法
1創(chuàng)建一個(gè)新的實(shí)驗(yàn)表 create table test as select * from dba_objects; |
2收集統(tǒng)計(jì)信息,這里注意方法是 size auto , Oracle 自己決定根據(jù)列的統(tǒng)計(jì)信息(sys.col_usage$)以及列的數(shù)據(jù)傾斜程度(均勻分布程度)決定哪些列需要收集直方圖 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查看統(tǒng)計(jì)信息 select a.column_name, b.num_rows, a.num_distinct Cardinality, round(a.num_distinct / b.num_rows * 100, 2) selectivity, a.histogram, a.num_buckets from dba_tab_col_statistics a, dba_tables b where a.owner = b.owner and a.table_name = b.table_name and a.owner = 'SCOTT' and a.table_name = 'TEST'; 從上面的結(jié)果發(fā)現(xiàn) HISTOGRAM返回的是none 沒有直方圖信息,是因?yàn)槲覀儧]有select查詢, |
4接著我們執(zhí)行select查詢, SELECT COUNT(*) FROM TEST WHERE OWNER='SCOTT'; 再次收集統(tǒng)計(jì)信息方法同步驟2和再次查看是否收集直方圖同步驟3 發(fā)現(xiàn)有where條件就可以收集直方圖 |
實(shí)驗(yàn) size repeat 的方法
1創(chuàng)建一個(gè)新的實(shí)驗(yàn)表 create table test as select * from dba_objects; |
2.收集統(tǒng)計(jì)信息,這里我們使用的size repeat只在已經(jīng)有直方圖的列上重新收集直方圖. repeat 會(huì)確保在全局級(jí)別上對(duì)已經(jīng)存在直方圖的列重新收集直方圖. |
BEGIN DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', tabname => 'TEST', estimate_percent => 30, method_opt => 'for all columns size repeat', no_invalidate => FALSE, degree => 1, cascade => TRUE); END; / 3查看統(tǒng)計(jì)信息 select a.column_name, b.num_rows, a.num_distinct Cardinality, round(a.num_distinct / b.num_rows * 100, 2) selectivity, a.histogram, a.num_buckets from dba_tab_col_statistics a, dba_tables b where a.owner = b.owner and a.table_name = b.table_name and a.owner = 'SCOTT' and a.table_name = 'TEST'; |
沒有直方圖的信息 |
實(shí)驗(yàn) 對(duì)某個(gè)列(test表的owner列)收集直方圖
BEGIN DBMS_STATS.GATHER_TABLE_STATS(ownname => 'SCOTT', tabname => 'TEST', estimate_percent => 30, method_opt => 'for owner columns size skewonly', no_invalidate => FALSE, degree => 1, cascade => TRUE); END; / 這里 for all 換成for owner |
到此,關(guān)于“怎么理解Oracle統(tǒng)計(jì)信息”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。