溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么理解Oracle統(tǒng)計(jì)信息

發(fā)布時(shí)間:2021-11-11 16:23:39 來(lái)源:億速云 閱讀:208 作者:iii 欄目:關(guān)系型數(shù)據(jù)庫(kù)

這篇文章主要介紹“怎么理解Oracle統(tǒng)計(jì)信息”,在日常操作中,相信很多人在怎么理解Oracle統(tǒng)計(jì)信息問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”怎么理解Oracle統(tǒng)計(jì)信息”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

  1. 統(tǒng)計(jì)信息的常用的腳本

DBMS_STATS.GATHER_TABLE_STATS參數(shù)

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的取值如下:

  • for all columns:統(tǒng)計(jì)所有的histograms

  • for all indexed columns:統(tǒng)計(jì)所有index列的histograms

  • for all hidden coloumns:統(tǒng)計(jì)hidden列的histograms

  • for columns  SIZE  | REPEAT | AUTO | SKEWONLY 統(tǒng)計(jì)指定列的histograms,N的取值范圍是0-254

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ì)信息。

非分區(qū)表:

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;

/

對(duì)分區(qū)表收集統(tǒng)計(jì)信息

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

腳本中的參數(shù)講解

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%

怎么理解Oracle統(tǒng)計(jì)信息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ū)名

判斷某個(gè)表的統(tǒng)計(jì)信息是否過(guò)期腳本

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;

怎么理解Oracle統(tǒng)計(jì)信息可以發(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';


怎么理解Oracle統(tǒng)計(jì)信息

  1. 收集統(tǒng)計(jì)信息注意方法

實(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'

怎么理解Oracle統(tǒng)計(jì)信息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條件就可以收集直方圖怎么理解Oracle統(tǒng)計(jì)信息

實(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';

怎么理解Oracle統(tǒng)計(jì)信息沒有直方圖的信息

實(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í)用的文章!

向AI問一下細(xì)節(jié)

免責(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)容。

AI