oracle 對象統計信息

對象統計信息的作用是幫助查詢優化器選擇更好的執行計劃。

比如,某一個表的索引clustering_factor非常的高,這個時候如果在where條件中指定column between A and B的限定條件來查詢,那麼查詢優化器有兩個選擇,一個是通過索引做索引範圍掃描,另一個是全表掃描。

因爲我們知道clustering_factor的值非常高,這時候做索引範圍掃描的開銷可能還會比全表掃描更高。所以我們期望是全表掃描。

但是如果數據庫中沒有關於這個索引數據對象的統計信息,那麼查詢優化器就不會瞭解到這個索引的 clustering_factor很高,那麼查詢優化器就有可能選擇索引範圍掃描的執行計劃,這樣就會產生一個低效的執行計劃。 所以我們可以看到,對象的統計信息的重要。

下面瞭解一下對象的統計信息。



1. 對象統計信息有哪幾種類型

有三種類型的對象統計信息:表統計,列統計,索引統計。


對象

表/索引級別統計

分區級別統計

子分區級別統計

user_tab_statistics

user_tables

user_tab_statistics

user_tables

user_tab_statistics

user_tables

user_tab_col_statistics

user_tab_histograms

user_part_col_statistics

user_part_histograms

user_subpart_col_statistics

user_subpart_histograms

索引

user_ind_statistics

user_indexes

user_ind_statistics

user_ind_partitions

user_ind_statistics

user_ind_subpartitions


爲了測試,我們創建如下表並手動蒐集統計信息。

CREATE TABLE t

AS

SELECT ROWNUM AS id,

       ROUND(DBMS_RANDOM.normal*1000) AS val1,

       100+ROUND(LN(ROWNUM/3.25+2)) AS val2,

       100+ROUND(LN(ROWNUM/3.25+2)) AS val3,

       DBMS_RANDOM.string('p',250) AS pad

FROM all_objects

WHERE ROWNUM<=1000

ORDER BY dbms_random.value;

 

UPDATE t SET val1=NULL WHERE val1<0;

ALTER TABLE t ADD CONSTRAINT t_pk PRIMARY KEY(id);

CREATE INDEX t_val1_i ON t(val1);

CREATE INDEX t_val2_i ON t(val2);

 

 

 

BEGIN

  dbms_stats.gather_table_stats(

  ownname => 'SYS',

  tabname =>'T',

  method_opt => 'for all columns size skewonly',

  cascade => TRUE);

END;

 


下面詳細說一下表,列,索引的統計信息。


1.1   表統計信息

表統計信息從user_tab_statistics中可以得到。

       SELECT           

       num_rows,blocks,empty_blocks,avg_space,chain_cnt,avg_row_len

       FROM

       user_tab_statistics

       WHERE

       table_name = 'T';

這裏要注意的是empty_blocks表示高水位以上的數據塊,這裏爲0,因爲dbms_stat不計算其值。Avg_space表示數據塊平均空閒空間(字節),這裏也不計算,設置爲0。Chain_cnt 行鏈接和航遷移總數,也不計算設置爲零。Avg_row_len table中平均行的長度(字節)。


1.2   列統計信息

列統計信息有兩種,普通列統計信息和直方圖。先看一下普通列統計信息。

普通列統計信息

SELECT column_name,

       num_distinct,

       low_value,

       high_value,

       density,

       num_nulls,

       avg_col_len,

       histogram,num_buckets

FROM   user_tab_col_statistics

WHERE  table_name ='T';

        Num_distinct 該列中唯一值的數量。

        Low_value 該列的最小值,存儲爲oracle內部格式,對字符串至存儲前32字節。

        High_value 該列的最大值,存儲爲oracle內部格式,對字符串至存儲前32字節。

        Density 0到1之間的一個小數。接近0表示對該列的過濾可以過濾掉大多數行(選擇性較強),接近1表示選擇性較弱。沒有直方圖的話其值爲1/num_distinct。如果有直方圖,則根據直方圖計算。

        Histograms 是否有直方圖,如果有是那種類型。

        Num_buckets 直方圖裏桶數。沒有直方圖則桶數爲1,最大桶數爲254。

直方圖

  查詢優化器原則上認爲數據是均勻分佈的,就如表t的主鍵列id。這一列的值分佈很均勻,在1到1000上平均分布。然而有時數據的分佈並不均勻。那麼這時查詢優化器需要額外的信息才能做出正確的判斷。比如我們已經知道了val2列的數據分佈如下:

SQL> SELECT val2 as val2,count(*) FROM t GROUP BY val2 ORDER BY val2;

 

      VAL2   COUNT(*)

---------- ----------

       101          8

       102         25

       103         68

       104        185

       105        502

       106        212

 

6 rows selected

如果有一條查詢語句以val2=105做過濾條件,這時查詢優化器如何選擇訪問路徑?很可能查詢優化器會選擇索引掃描,因爲它並不知道這一列值爲105的佔了一半還多。如果查詢優化器知道了這個信息,那麼它就可以果斷的選擇全表掃描,因爲在返回大量數據的情況下,全表掃描比索引開銷更小。(當然,本例中t表一共纔有1000條數據,所以無論是全表還是索引掃描都會很快返回結果)

 

  要獲得這些額外信息,查詢優化器可以查詢直方圖。直方圖有兩種,頻率直方圖和等高直方圖。他們的區別主要在於桶數和唯一值的個數。直方圖的桶數最大爲254。如果唯一值的個數小於等於254就可以建立頻率直方圖,每一個唯一值一個桶。如果唯一值的個數大於254則要建立等高直方圖。

 

  頻率直方圖,下面的查詢查詢了表t val2列上的頻率直方圖。

SQL> SELECT endpoint_value,

  2         endpoint_number,

  3         endpoint_number - lag(endpoint_number,1,0) OVER (ORDER BY endpoint_number) AS frequency

  4  FROM   user_tab_histograms

  5  WHERE table_name='T' AND column_name='VAL2'

  6  ORDER BY endpoint_number

  7  /

 

 

 

ENDPOINT_VALUE ENDPOINT_NUMBER  FREQUENCY

-------------- --------------- ----------

           101               8          8

           102              33         25

           103             101         68

           104             286        185

           105             788        502

           106            1000        212

 

6 rows selected

從上面的查詢可以瞭解到,endpoint_value代表的是直方圖中桶內唯一值的內容。Endpoint_number存儲的是頻率。不過這個頻率是累加頻率。

 

等高直方圖,下面的語句手動建立了一個等高直方圖。

SQL> SELECT count(*) , max(val2) AS endpoint_value , endpoint_number

  2  FROM (SELECT val2, ntile(5) over(order by val2) as endpoint_number FROM t)

  3  GROUP BY endpoint_number

  4  ORDER BY endpoint_number

  5  /

 

  COUNT(*) ENDPOINT_VALUE ENDPOINT_NUMBER

---------- -------------- ---------------

       200            104               1

       200            105               2

       200            105               3

       200            106               4

       200            106               5

 

關於直方圖的信息這裏講述的很不完全,需要查看額外的文檔具體瞭解。

1.3   擴展列的統計信息

        如果我們在where條件中這樣使用一個查詢條件upper(val2) = 105,那麼查詢優化器是無法使用統計信息的。而相應的我們可以這樣處理,創建一個upper(val2)的虛列,然後在這個虛列上收集統計信息。不過我們要了解的下面的這個函數可以幫我們完成從創建虛列到收集虛列統計信息的全過程。

SELECT dbms_stats.create_extended_stats(ownname => 'SYS',tabname => 'T',extension => '(UPPER(PAD))') FROM DUAL;

1.4   索引統計信息

SQL> SELECT INDEX_NAME,

  2  BLEVEL,

  3  LEAF_BLOCKS,

  4  DISTINCT_KEYS,

  5  NUM_ROWS,

  6  CLUSTERING_FACTOR

  7  FROM DBA_IND_STATISTICS WHERE TABLE_NAME='IND_GOOD';

 

上面主要講解了各種類型的統計信息,以及如何查詢這些統計信息,下面講解一下怎樣生成這些統計信息。

2.      收集對象統計信息

收集統計信息要用dbms_stats工具包來收集。裏面提供了多個過程:

Gater_database_stats

Gather_dictionary_stats

Gather_fixed_objects_stats

Gather_schema_stats

Gather_table_stats

Gather_index_stats

這些存儲過程每個都需要多個參數,這些參數可以分成三大組,第一組,指明對象,第二組,指明收集選項,第三組指明覆蓋當前的統計信息之前是否備份。

參數

數據庫

數據字典

固定對象

模式

索引

目標對象

 

 

 

 

 

 

Owner

 

 

 

Indname

 

 

 

 

 

tabname

 

 

 

 

 

partname

 

 

 

 

Comp_id

 

 

 

 

 

granularity

 

cascade

 

 

Gather_sys

 

 

 

 

 

Gather_temp

 

 

 

 

options

 

 

 

objlist

 

 

 

force

 

 

 

Obj_filter_list

 

 

 

收集選項

 

 

 

 

 

 

Estimate_percent

 

Block_sample

 

 

Method_opt

 

 

 No_invalidate

備份表

 

 

 

 

 

 

Stattab

Statid

statown

下面介紹一下這些參數的意義。

目標對象參數:

Ownname      指定schema名稱。

Indname       指定索引名稱。

Tabname      指定表的名稱

Partname      指定分區或者子分區的名稱。如果不指定,則收集所有分區的對象統計信息。

Comp_id       這個不明確。

Granularity     指定要處理的分區對象的統計級別。

Cascade      指明是否手機索引統計信息。

Gather_sys    指明是否手機sys用戶統計信息

Gather_temp  指明是否收集臨時表的統計信息。但要注意的是,dbms_stats運行時,會先commit,所以只有指定了on commit preserve rows的臨時表纔可以被處理。

Options           包含7個選項

                     Gather:           處理所有對象

                      Gatherauto     由系統決定那些對象要處理以及如何處理

                      Gatherstale    只處理信息失效的對象,注意,沒有統計信息的不算信失效。

                      Gatherempty  只處理沒有統計信息的對象

                      List auto         列出將用gather auto處理的對象

                      Liststale         列出將用gather stale處理的對象

                      Listempty      列出將用gather empty處理的對象

Objlist             該參數根據options的不同值返回被處理的對象列表。

Obj_filter_list   在目標對象滿足該參數指定的過濾條件時纔會收集統計信息

收集選項參數:

Estimate_percent指明是否採樣收集統計信息。值可以爲0.0000001到100。一百表示不採樣。常量 dbms_stats.auto_sample_size算作0,由系統決定採樣大小。

Block_sample                指明採樣是採用數據行採樣還是數據塊採樣。行採樣精確,塊採樣快捷。

Method_opt               指明是否收集直方圖統計信息還指明採樣的最大桶數。

                                    值的格式爲columns clause + size clause

                                    例如:for all columns size skewonly

                                    Columnsclause可取值有:

for all [indexed / hidden ] columns

                                    Sizeclause      可取值有:

size 1-254

                                                 Size skewonly 只收集skew列,桶數由系統決定

                                                 Size auto 同上,並且要加上where引用的列

                                                 Size repat 只是刷新現有直方圖

No_invalidate                收集了統計信息,很有可能有一些遊標就不適用了。那麼這時這個參數可以指定成三個值。

                                    True遊標不失效,這樣重新收集統計信息就沒意義了。

                                    False遊標立即失效,可能會造成集中大量解析遊標

                                    Dbms_stats.auto_invalidate遊標不立即失效,這樣可以避免集中解析問題。

備份表參數

Stattab                         指定存儲統計信息的備份表

Statid                           

Statown                      指定備份表的用戶名,默認是當前用戶。


發佈了29 篇原創文章 · 獲贊 7 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章