Oracle SQL CBO 優化器/優化程序 統計信息

  • 收集優化程序統計信息
  • 收集系統統計信息
  • 設置統計信息首選項
  • 使用動態採樣
  • 處理優化程序統計信息
  •  

    SQL CBO 優化器/優化程序 統計信息

     

    優化程序統計信息描述有關數據庫及其中對象的詳細資料。查詢優化程序使用這些統計信息,爲每個 SQL 語句選擇最佳的執行計劃。

    由於數據庫中的對象經常發生更改,所以必須定期更新統計信息,以使它們能夠準確地描述這些數據庫對象。統計信息由 Oracle DB 自動進行維護,您也可以使用 DBMS_STATS 程序包手動維護優化程序統計信息。

  • 描述數據庫以及數據庫中的對象
  • 查詢優化程序使用以下信息進行評估:
  • –謂詞的選擇性

    –每個執行計劃的成本

    –訪問方法、聯接順序和聯接方法

    –CPU 和輸入/輸出 (I/O) 成本

  • 與收集優化程序統計信息相比,對過時的統計信息進行刷新同樣重要。
  • –由系統自動收集

    –用戶使用 DBMS_STATS 手動收集

     

    優化程序統計信息的類型

  • 表統計信息:
  • –行數

    –塊數

    –平均行長度

  • 索引統計信息:
  • –B* 樹級別

    –唯一鍵

    –葉塊數量

    –聚簇因子

  • 系統統計信息:
  • –I/O 性能及利用率

    –CPU 性能及利用率

  • 列統計信息:
  • –基本統計信息:相異值數量、空值數量、平均長度、最小值、最大值

    –直方圖(列數據有偏差時的數據分佈)

    –擴展的統計信息

    幻燈片中列出了大多數優化程序統計信息。

    自 Oracle Database 10g 開始,在創建或重建索引時會自動收集索引統計信息。

    注:此幻燈片提及的統計信息是優化程序統計信息,是爲查詢優化創建的,存儲在數據字典中。不應將此類統計信息與 V$ 視圖中顯示的性能統計信息相混淆。

     

     

    表統計信息 (DBA_TAB_STATISTICS)

    NUM_ROWS

    這是基數計算的基礎。如果表是嵌套循環聯接的驅動表,則行計數尤爲重要,因爲它定義了內部表被探測多少次。

    BLOCKS

    已使用數據塊的數量。塊計數與 DB_FILE_MULTIBLOCK_READ_COUNT 組合在一起給出了基表訪問成本。

    EMPTY_BLOCKS

    表中空的(從未使用的)數據塊數量。這是已使用數據塊和高水位標記之間的塊。

    AVG_SPACE

    分配給表的數據塊中空閒空間的平均數量(以字節爲單位)。

    CHAIN_CNT

    這是表中從一個數據塊鏈接到另一個數據塊、或者移植到了新塊,且需要用鏈接來保留原有 ROWID 的行的數量。

    AVG_ROW_LEN

    表中行的平均長度(以字節爲單位)。

    STALE_STATS

    指明統計信息在相應表中是否有效。

     

  • 用於確定以下項:
  • –表訪問成本

    –聯接基數

    –聯接順序

  • 收集的一些統計信息包括:
  • –行計數 (NUM_ROWS)

    –塊計數 (BLOCKS) 精確值

    –空塊數 (EMPTY_BLOCKS) 精確值

    –每個塊的平均空閒空間 (AVG_SPACE)

    –鏈接行的數量 (CHAIN_CNT)

    –平均行長度 (AVG_ROW_LEN)

    –統計信息狀態 (STALE_STATS)

     

    索引統計信息 (DBA_IND_STATISTICS)

     

  • 用於確定以下項:
  • –全表掃描與索引掃描

  • 收集的統計信息包括:
  • –B* 樹級別 (BLEVEL) 精確值

    –葉塊計數 (LEAF_BLOCKS)

    –聚簇因子 (CLUSTERING_FACTOR)

    –唯一鍵 (DISTINCT_KEYS)

    –它指明索引中的每個相異值平均出現在多少個葉塊中 (AVG_LEAF_BLOCKS_PER_KEY)

    –索引中的每個相異值所指向的表數據塊的平均數量 (AVG_DATA_BLOCKS_PER_KEY)

    –索引中的行數 (NUM_ROWS)

     

    一般來說,要選擇索引訪問,優化程序要求針對索引列的前綴使用一個謂詞。但是,如果沒有謂詞,並且查詢中引用的所有列都存在於索引中,則優化程序會考慮使用完全索引掃描,而不是全表掃描。

    BLEVEL

    該信息用於計算葉塊查找成本。它指明索引從根塊到葉塊的深度。深度爲“0”表明根塊和葉塊是相同的。

    LEAF_BLOCKS

    該信息用於計算完全索引掃描成本。

    CLUSTERING_FACTOR

    它基於索引的值測量表中行的順序。如果該值接近塊數量,則表明表的順序良好。在這種情況下,一個葉塊中的索引項通常指向同一數據塊中的行。如果該值接近行數量,則表明表的順序是隨機的。在這種情況下,同一葉塊中的索引項可能沒有指向同一數據塊中的行。

    STALE_STATS

    指明統計信息在相應索引中是否有效。

     

    DISTINCT_KEYS

    相異索引值的數量。對於強制執行 UNIQUE 和 PRIMARY KEY 約束條件的索引,此值等於錶行數。

    AVG_LEAF_BLOCKS_PER_KEY

    它指明索引中的每個相異值平均出現在幾個葉塊中,該值舍入到最近的整數。對於強制執行 UNIQUE 和 PRIMARY KEY 約束條件的索引,此值始終等於一 (1)。

    AVG_DATA_BLOCKS_PER_KEY

    索引中的每個相異值所指向的表數據塊的平均數量,舍入到最近的整數。對於每個給定的索引列值,該統計信息表示其行中包含該值的數據塊的平均數量。

    NUM_ROWS

    索引中的行數。

    索引聚簇因子

     

    系統按塊執行輸入/輸出 (I/O)。所以,優化程序是否使用全表掃描取決於所訪問的塊的百分比,而不是行百分比。這稱作索引聚簇因子。如果每個塊都包含單個行,則訪問的行數和訪問的塊數是相同的。

    但是,大多數表在每個塊中都包含多個行。因此,所需數量的行可能聚集在幾個塊中,也可能散佈在大量塊中。除 B* 樹級別,葉塊數量以及索引選擇性之類的信息之外,索引範圍掃描的成本公式還包括聚簇因子。這是因爲較小的聚簇因子表示行集中在表中的少量塊中。較大的聚簇因子表示行隨機分佈在表中各個塊之間。所以,較大的聚簇因子意味着使用索引範圍掃描按 ROWID 獲取行會花費較多的成本,因爲需要訪問表中較多的塊才能返回數據。在實際環境中,因爲葉塊數量和 B* 樹高度與聚簇因子和表選擇性相比,相對較小,所以聚簇因子在決定索引範圍掃描的成本方面似乎起着重要作用。

    注:如果某個表有多個索引,則一個索引的聚簇因子可能較小,而同時另一個索引的聚簇因子可能較大。如果嘗試重新組織此表以改進一個索引的聚簇因子,則可能會導致另一個索引的聚簇因子性能降低。

     

    在收集索引的統計信息時,系統會在 DBA_INDEXES 視圖的 CLUSTERING_FACTOR 列中計算聚簇因子。計算方式相對來講比較簡單。從左到右讀取索引,對於每個索引項,如果相應行所在的塊不同於上一行所在的塊,將聚簇因子加一。基於此算法,聚簇因子最小可能值是塊數量,最大可能值是行數量。

    幻燈片中的示例說明了聚簇因子如何影響成本。假設存在下列情況:有一個表包含 9 行,在此表的 col1 上有一個非唯一索引,c1 列當前存儲的值爲 A、B 和 C,此表僅有三個 Oracle 塊。

  • 情形 1:如果組織表中的行,使索引值分散在各個表塊中(而不是並列排置),則索引聚簇因子較高。
  • 情形 2:如果將具有相同值的行並列排置在相同的塊中,則這些行的索引聚簇因子
    較低。
  • 注:對於位圖索引,聚簇因子不適用,因而不會使用。

     

    列統計信息 (DBA_TAB_COL_STATISTICS)

  • 列的相異值計數 (NUM_DISTINCT)
  • 下限值 (LOW_VALUE) 精確值
  • 上限值 (HIGH_VALUE) 精確值
  • 空值數量 (NUM_NULLS)
  • 非常用值的選擇性估計 (DENSITY)
  • 直方圖存儲桶數量 (NUM_BUCKETS)
  • 直方圖類型 (HISTOGRAM)
  • NUM_DISTINCT 用在選擇性計算中,例如,1/NDV

    LOW_VALUEHIGH_VALUE:基於成本的優化程序 (CBO) 假定所有數據類型的值在下限值和上限值之間是均勻分佈的。這些值用於確定範圍選擇性。

    NUM_NULLS 對可爲空值的列以及 IS NULL 和 IS NOT NULL 謂詞的選擇性很有幫助。

    DENSITY 僅與直方圖相關。它可用作非常用值的選擇性估計。可以將其視爲在此列中發現某個特殊值的概率。它的計算取決於列是否有一個直方圖以及直方圖的類型。

    NUM_BUCKETS 是列直方圖中存儲桶的數量。

    HISTOGRAM 表明直方圖是否存在或直方圖類型:NONE、FREQUENCY、HEIGHT BALANCED

     

    直方圖

  • 優化程序假定數據均勻分佈;當數據有偏差時,這可能會導致訪問計劃不太理想。
  • 直方圖:
  • –存儲其它列分佈信息

    –在數據分佈不均勻的情況下給出更準確的選擇性估計。

  • 使用無限的資源,您可以存儲每個不同的值以及與該值對應的行數量。
  • 如果相異值很多,這會變得難以管理,此時應使用其它
    方法:
  • –頻率直方圖(#相異值 ≤ #存儲桶)

    –高度平衡直方圖(#存儲桶 < #相異值)

  • 它們存儲在 DBA_TAB_HISTOGRAMS 中。
  • 直方圖捕獲列中不同值的分佈情況,因此會生成更準確的選擇性估計。如果列包含有偏差的數據,或包含在重複數量上有很大變化的值,則針對這類列創建直方圖可以幫助查詢優化程序生成準確的選擇性估計,並針對索引使用、聯接順序、聯接方法等等做出更好的

    決定。

    如果沒有直方圖,則假定數據均勻分佈。如果某個列的直方圖可用,則評估人員會使用該圖,而不使用相異值數量。

    創建直方圖時,Oracle DB 使用兩種不同類型的直方圖表示方法,具體取決於在相應列中找到的相異值數量。如果您的數據集包含的相異值少於 254 個,並且沒有指定直方圖存儲桶數量,則系統會創建頻率直方圖。如果相異值數量大於所需的直方圖存儲桶數量,則系統會創建高度平衡直方圖。

    在以下字典視圖中可以找到有關直方圖的信息:DBA_TAB_HISTOGRAMS、DBA_PART_HISTOGRAMS 和 DBA_SUBPART_HISTOGRAMS

    注: 在統計信息收集方面,收集直方圖統計信息是一項最耗費資源的操作。

     

    頻率直方圖

    頻率直方圖在幻燈片的示例中,假定您有一個包含 40,001 個數字的列,但相異值只有 10 個:1、3、5、7、10、16、27、32、39 和 49。值 10 是最常用的值,出現了 16,293 次。

    當請求的存儲桶數量等於(或大於)相異值數量時,您可以存儲每個不同的值並記錄精確的基數統計信息。在這種情況下,在 DBA_TAB_HISTOGRAMS 中,ENDPOINT_VALUE 列存儲列值,ENDPOINT_NUMBER 列存儲該列值的行計數。

    該行計數以累積形式進行存儲,這樣範圍掃描可以減少一些計算。爲了清楚起見,幻燈片中使用曲線顯示行計數的實際數量;僅 ENDPOINT_VALUE 和 ENDPOINT_NUMBER 列存儲在數據字典中。

     

    查看頻率直方圖

    幻燈片中的示例顯示了查看頻率直方圖的方法。由於 INVENTORIES 表的 WAREHOUSE_ID 列中相異值的數量爲 9,並且請求的存儲桶數量爲 20,所以系統會自動創建一個具有 9 個存儲桶的頻率直方圖。可以在 USER_TAB_COL_STATISTICS 視圖中查看此信息。

    要查看直方圖本身,可以查詢 USER_HISTOGRAMS 視圖。您可以看到 ENDPOINT_NUMBER 和 ENDPOINT_VALUE,前者對應着相應 ENDPOINT_VALUE 的累積頻率,後者在本例中代表列數據的實際值。

    注:本課稍後將對 DBMS_STATS 程序包進行介紹。

     

     

    BEGIN
     DBMS_STATS.gather_table_STATS (OWNNAME=>'OE', TABNAME=>'INVENTORIES',
           METHOD_OPT => 'FOR COLUMNS SIZE 20 warehouse_id');
    END;

    SELECT column_name, num_distinct, num_buckets, histogram
    FROM   USER_TAB_COL_STATISTICS
    WHERE  table_name = 'INVENTORIES' AND
           column_name = 'WAREHOUSE_ID';
     
    COLUMN_NAME  NUM_DISTINCT NUM_BUCKETS HISTOGRAM
    ------------ ------------ ----------- ---------
    WAREHOUSE_ID            9           9 FREQUENCY

    SELECT endpoint_number, endpoint_value
    FROM   USER_HISTOGRAMS
    WHERE  table_name = 'INVENTORIES' and column_name = 'WAREHOUSE_ID'
    ORDER BY endpoint_number;
     
    ENDPOINT_NUMBER ENDPOINT_VALUE
    --------------- --------------
    36                           1
    213                          2
    261                          3

    高度平衡直方圖

     

    在高度平衡直方圖中,列值被分成若干段,每個段包含的行數幾乎相同。直方圖可表明在值範圍中端點終止的位置。在幻燈片示例中,假定您有一個包含 40,001 個數字的列。但相異值只有 10 個:1、3、5、7、10、16、27、32、39 和 49。值 10 是最常用的值,出現了 16,293 次。如果存儲桶數量少於相異值數量,則 ENDPOINT_NUMBER 記錄存儲桶數量,而 ENDPOINT_VALUE 記錄與此端點對應的列值。在示例中,每個存儲桶包含的行數是總行數的五分之一,即 8000。

    根據此假設,值 10 的出現次數在 8000 和 24000 之間。因此您確定值 10 是一個常用值。

    此類型的直方圖適用於常用值的等式謂詞和範圍謂詞。

    不記錄每個存儲桶的行數,因爲這可以從值的總數以及所有存儲桶都包含相同數量的值這一事實推導出來。在本例中,值 10 是一個常用值,因爲它跨越了多個端點值。爲了節約空間,直方圖不實際存儲重複的存儲桶。由於此原因,在幻燈片的示例中,不會在 DBA_TAB_HISTOGRAMS 中記錄存儲桶 2(端點值爲 10)。

    注:本例中的密度統計值將爲 1/9 x 4/5 = 0.088 或 8.8%(9=#NPV 和 4=#NPB)。此值將用於非常用值的選擇性計算。

     

    幻燈片中的示例顯示了查看高度平衡直方圖的方法。由於 INVENTORIES 表的 QUANTITY_ON_HAND 列中相異值的數量爲 237,並且請求的存儲桶數量爲 10,所以系統會自動創建一個具有 10 個存儲桶的高度平衡直方圖。可以在 USER_TAB_COL_STATISTICS 視圖中查看此信息。

    要查看直方圖本身,可以查詢 USER_HISTOGRAMS 視圖。您可以看到與存儲桶數量對應的 ENDPOINT_NUMBER,以及與端點的末端值對應的 ENDPOINT_VALUE。

    注:本課稍後將對 DBMS_STATS 程序包進行介紹。

     

     

    BEGIN
      DBMS_STATS.gather_table_STATS(OWNNAME =>'OE', TABNAME=>'INVENTORIES', 
      METHOD_OPT => 'FOR COLUMNS SIZE 10 quantity_on_hand');
    END;

    SELECT column_name, num_distinct, num_buckets, histogram 
      FROM USER_TAB_COL_STATISTICS
     WHERE table_name = 'INVENTORIES' AND column_name = 'QUANTITY_ON_HAND';
     
    COLUMN_NAME                    NUM_DISTINCT NUM_BUCKETS HISTOGRAM
    ------------------------------ ------------ ----------- ---------------
    QUANTITY_ON_HAND                        237          10 HEIGHT BALANCED

    SELECT endpoint_number, endpoint_value 
    FROM USER_HISTOGRAMS
    WHERE table_name = 'INVENTORIES' and column_name = 'QUANTITY_ON_HAND'
    ORDER BY endpoint_number;
     
    ENDPOINT_NUMBER ENDPOINT_VALUE
    --------------- --------------
                  0              0
                  1             27
                  2             42
                  3             57

     

    直方圖注意事項

  • 如果列的數據分佈有大幅偏差,則直方圖很有用。
  • 對於以下情況,直方圖沒有太大用處:
  • –列沒有出現在 WHERE 或 JOIN 子句中

    –列的數據分佈較均勻

    –對唯一性列使用了等式謂詞

  • 存儲桶的最大數量等於 254 和相異值數量這兩者之中的最小值。
  • 除非直方圖能夠顯著改善性能,否則不要使用直方圖。
  • 直方圖只有在能夠反映給定列的當前數據分佈時纔是有用的。在數據分佈保持不變的情況下,列中的數據可能會更改。如果列的數據分佈頻繁發生變化,您必須頻繁地重新計算其直方圖。

    如果您要爲其創建直方圖的列包含有高度偏差的數據,則直方圖很有用。

    然而,對於沒有出現在 SQL 語句的 WHERE 子句中的列,沒有必要爲其創建直方圖。同樣,也沒有必要爲數據分佈較均勻的列創建直方圖。

    另外,直方圖對聲明爲 UNIQUE 的列也沒有用處,因爲此時選擇性是顯而易見的。此外,存儲桶的最大數量爲 254,可能更低,具體取決於相異列值的實際數量。直方圖會影響性能,只有在直方圖能夠顯著改善查詢計劃時,才應使用它們。如果數據分佈很均勻,則優化程序不使用直方圖就可以相當準確地估算出執行一個特殊語句所需的成本。

    注:字符列有一些不同的行爲,因爲對於任何字符串只有前 32 個字節被存儲爲直方圖

    數據。

     

    多列統計信息:概覽

     

    使用 Oracle Database 10g,在以下有限的情況下,查詢優化程序在計算多個謂詞的選擇性時,將考慮列之間的相互關係:

  • 如果連接謂詞的所有列與級聯索引關鍵字的所有列匹配,並且謂詞是等值聯接中使用的等式,則優化程序將使用索引中的唯一鍵 (NDK) 的數量來估計選擇性 (1/NDK)。
  • 如果將 DYNAMIC_SAMPLING 設置爲級別 4,則查詢優化程序將使用動態採樣來評估涉及同一個表中多個列的複雜謂詞的選擇性。但是,樣本的大小很小,並且分析時間有所增加。因此,從統計學的角度來看樣本可能不準確,並且可能會弊大於利。
  • 在其它所有情況下,優化程序將假定複雜謂詞中所用的列的值互不相關。優化程序會通過將各個謂詞的選擇性相乘來估計連接謂詞的選擇性。如果列之間存在相關性,則此方法會低估選擇性。爲了避免此問題,Oracle Database 11g 允許您收集、存儲並使用以下統計信息來捕獲兩個或更多列(也稱爲列組)之間的功能相關性:相異值的數量、空值的數量、頻率直方圖和密度。

     

    例如,假定有一個 VEHICLE 表,其中存儲了有關汽車的信息。MAKE 和 MODEL 列是高度相關的,因爲 MODEL 決定 MAKE。這是一種強依賴關係,優化程序應將這兩個列看成是高度相關的兩個列。可以使用 CREATE_EXTENDED_STATS 函數將該關係傳送給優化程序(如幻燈片上的示例所示),然後計算所有列的統計信息(包括創建的相關組的統計

    數據)。

    優化程序僅對等式謂詞使用多列統計信息。

    附註

  • CREATE_EXTENDED_STATS 函數會返回一個虛擬的隱藏列名稱,如 SYS_STUW_5RHLX443AN1ZCLPE_GLE4。
  • 根據幻燈片中的示例,可以使用以下 SQL 確定名稱:
    select dbms_stats.show_extended_stats_name(‘jfv’,’vehicle’,'(make,model)’) from dual
  • 創建統計信息擴展名之後,可以通過使用 ALL|DBA|USER_STAT_EXTENSIONS 視圖檢索它們。
  •  

    表達式統計信息:概覽

     

    與列表達式相關的謂詞是查詢優化程序的一個重要的問題。計算 function(Column) = constant 形式的謂詞的選擇性時,優化程序將假定靜態選擇性值爲 1%。此方法是錯誤的,因爲這會導致優化程序生成不太理想的計劃。

    查詢優化程序已得到了擴展,可以在有限的幾種情況下更好地處理此類謂詞。在這些情況下,函數保留列的數據分佈特徵,因而允許優化程序使用列統計信息。例如,TO_NUMBER 就是此類函數之一。

    此外,還對相應功能做了進一步增強,可在查詢優化過程中對內置函數求值,以便使用動態採樣來獲得更高的選擇性。最後,優化程序收集所創建的虛擬列的統計信息以支持基於函數的索引。

    但是,這些解決方案或者侷限於特定的函數類,或者僅適合於用於創建基於函數的索引的表達式。通過使用 Oracle Database 11g 中的表達式統計信息,您可以使用更加通用的解決方案;這些解決方案包括了用戶定義的任意函數,並且與是否存在基於函數的索引無關。如幻燈片中的示例所示,此功能將依靠虛擬列基礎結構來創建列表達式的統計信息。

     

     

    收集系統統計信息

     

  • 通過系統統計信息,CBO 可以使用 CPU 和 I/O 特徵。
  • 必須定期收集系統統計信息;這不會使所緩存的計劃失效。
  • 收集系統統計信息等同於分析一個指定期間內的系統活動:
  • 過程:
  • –DBMS_STATS.GATHER_SYSTEM_STATS

    –DBMS_STATS.SET_SYSTEM_STATS

    –DBMS_STATS.GET_SYSTEM_STATS

  • GATHERING_MODE:
  • –NOWORKLOAD|INTERVAL

    –START|STOP

     

    使用系統統計信息,優化程序可以考慮系統的 I/O 和 CPU 性能以及利用情況。針對每個候選計劃,優化程序計算 I/O 和 CPU 成本的估計值。要選擇最高效的、I/O 和 CPU 成本達到最佳比例的計劃,需要了解系統特徵,這一點很重要。系統 CPU 和 I/O 特徵並不總是保持不變,它們與許多因素相關。使用系統統計信息管理例程,可以捕獲系統在最常見工作量下運行時一定時間間隔內的統計信息。例如,數據庫應用程序可以在白天處理聯機事務處理 (OLTP) 事務,在晚上運行 OLAP 報表。這兩種狀態的統計信息您都可以收集,並且可以根據需要激活適當的 OLTP 或 OLAP 統計信息。這樣優化程序便可以針對可用的系統資源計劃生成相關的成本。系統生成系統統計信息時,會分析指定期間內的系統活動。與表、索引或列統計信息不同,系統統計信息更新後,系統不會使已分析的 SQL 語句失效。所有新的 SQL 語句都使用新的統計信息進行解析。

    我們強烈建議您收集系統統計信息。可以使用 DBMS_STATS.GATHER_SYSTEM_STATS 例程在用戶定義的時間段內收集系統統計信息。也可以使用 DBMS_STATS.SET_SYSTEM_STATS 顯式設置系統統計信息值。可使用 DBMS_STATS.GET_SYSTEM_STATS 驗證系統統計信息。

     

    使用 GATHER_SYSTEM_STATS 過程時,應指定 GATHERING_MODE 參數:

  • NOWORKLOAD:這是默認設置。此模式可捕獲 I/O 系統的特徵。收集統計信息可能會花費幾分鐘的時間,具體取決於數據庫大小。在此期間系統會估算 I/O 系統的平均讀取尋道時間和傳輸速度。此模式適用於所有工作量。建議您在創建數據庫和表空間後運行 GATHER_SYSTEM_STATS (‘noworkload’)。
  • INTERVAL:捕獲指定間隔內的系統活動。此參數與指定捕獲時間量的 interval 參數組合在一起發揮作用。您應提供一個以分鐘爲單位的間隔值,之後系統會在字典或登臺表中創建或更新系統統計信息。可以使用 GATHER_SYSTEM_STATS (gathering_mode=>’STOP’) 提前停止收集信息。
  • START | STOP:獲取指定開始時間和停止時間之間的系統活動,用該過去時間段內的統計信息刷新字典或登臺表。
  • 注:自 Oracle Database 10gR2 開始,系統會在啓動時自動收集重要的系統統計信息。

     

    收集系統統計信息:示例

     

     

    幻燈片中的示例顯示了在白天處理 OLTP 事務、在晚上運行報表的數據庫應用程序。

    首先,必須在白天收集系統統計信息。在本例中,收集過程在 120 分鐘後結束,統計信息存儲在 mystats 表中。

    然後在晚上收集系統統計信息。收集過程在 120 分鐘後結束,統計信息存儲在 mystats 表中。

    通常,收集系統統計信息時使用幻燈片中的語法。在調用指定了 INTERVAL 參數的 GATHER_SYSTEM_STATS 過程之前,必須使用 SQL> alter system set job_queue_processes = 1; 之類的命令激活作業進程。也可以調用具有不同參數的相同過程來啓用手動收集,而不使用作業。

    適當的時候,可以在收集的統計信息之間進行切換。請注意,可以通過提交一個作業用正確的統計信息更新字典,使此過程自動化。在白天,可使用一個作業導入 OLTP 統計信息用於白天的運行,在晚上,可使用另一個作業導入聯機分析處理 (OLAP) 統計信息用於晚上的運行。

     

     

  • 手動在數據字典中啓動系統統計信息收集:
  • SQL> EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS( –

      2  gathering_mode => ‘START’);

     

  • 生成工作量。
  • 結束收集系統統計信息:
  • SQL> EXECUTE DBMS_STATS.GATHER_SYSTEM_STATS( –

      2  gathering_mode => ‘STOP’);

    上一幻燈片中的示例顯示瞭如何通過 DBMS_STATS.GATHER_SYSTEM_STATS 過程的內部參數使用作業收集系統統計信息。要手動收集系統統計信息,可以使用此過程的另一個參數,如幻燈片中所示。

    首先,必須啓動系統統計信息的收集過程,在確定實例中已生成了具有代表性的工作量後,可以隨時結束收集過程。

    本示例直接在數據字典中收集系統統計信息。

     

     

    用於收集統計信息的機制

  • 自動統計信息收集
  • –gather_stats_prog 自動化任務

  • 手動統計信息收集
  • –DBMS_STATS 程序包

  • 動態採樣
  • 缺少統計信息時:
  •  

    Oracle DB 提供了幾種機制來收集統計信息。這些機制將在後面的幻燈片中詳細講述。建議您爲對象使用自動統計信息收集功能。

    注:當系統發現表缺少統計信息時,它會動態收集優化程序所需要的必需統計信息。但是,對於某些類型的表,它不會執行動態採樣,其中包括遠程表和外部表。在這些情況下以及動態採樣被禁用時,優化程序將使用默認的統計信息值。

     

    統計信息首選項:概覽

    自動統計信息收集功能是在 Oracle Database 10gR1 中引入的,用於減輕優化程序統計信息的維護工作。但是,在有些情況下,必須禁用該功能,並運行自己的腳本。其中的一個原因是缺少對象級別的控制。只要發現一小部分對象的默認收集統計信息選項的效果不佳,就必須鎖定統計信息,並使用您自己的選項單獨對其進行分析。例如,如果列包含頻率偏差很大的數據,則嘗試針對這些列自動確定合適樣本大小的功能 (ESTIMATE_PERCENT=AUTO_SAMPLE_SIZE) 不會有很好的效果。解決此問題的唯一方法就是用自己的腳本手動指定樣本大小。

    Oracle Database 11g 中的統計信息首選項功能具有一定的靈活性,因此,在有些對象需要不同於數據庫默認設置的設置時,也可以較靈活地使用自動統計信息收集功能來維護優化程序統計信息。

    通過此功能,您可以在對象級別或方案級別,將覆蓋 GATHER_*_STATS 過程的默認行爲的統計信息收集選項與自動優化程序統計信息收集任務關聯起來。可以使用 DBMS_STATS 程序包管理幻燈片中顯示的收集統計信息選項。

     

     

    可以在表級、方案級、數據庫級和全局級設置、獲取、刪除、導出和導入這些首選項。全局首選項用於沒有首選項的表,而數據庫首選項則用於設置針對所有表的首選項。以各種方式指定的首選項值的優先順序爲從外圈到內圈(如幻燈片中所示)。

    在幻燈片的圖形中,最後三個突出顯示的選項是 Oracle Database 11gR1 中新增的選項:

  • CASCADE 還收集索引統計信息。索引統計信息收集不是一個並行化操作。
  • ESTIMATE_PERCENT 是用於計算統計信息的行的估計百分比(空值代表所有行):有效範圍是 [0.000001,100]。使用常量 DBMS_STATS.AUTO_SAMPLE_SIZE 可讓系統自己決定適當的採樣範圍以獲得準確的統計信息。這是推薦的默認值。
  • NO_INVALIDATE 可能會使也可能不會使從屬遊標失效。如果將其設置爲 TRUE,則不會使從屬遊標失效。如果將其設置爲 FALSE,則此過程會立即使從屬遊標失效。使用 DBMS_STATS.AUTO_INVALIDATE 可讓系統自己決定何時使從屬遊標失效。這是默認設置。
  • PUBLISH 用於確定是將統計信息發佈到字典還是先將其存儲在臨時等待區中。
  • STALE_PERCENT 用於確定閾值級別,達到該級別時將認爲對象具有過時統計信息。該值是上次收集統計信息以來修改過的行數的百分比。示例僅將 SH.SALES 的值從默認值 10% 更改爲 13%。
  • DEGREE 決定用於計算統計信息的並行度。並行度的默認值爲空值,這表示使用由 CREATE TABLE 或 ALTER TABLE 語句的 DEGREE 子句指定的表默認值。使用常量 DBMS_STATS.DEFAULT_DEGREE 將基於初始化參數指定默認值。AUTO_DEGREE 值可自動決定並行度。此值可能是 1(串行執行),也可能是 DEFAULT_DEGREE(基於 CPU 數量和初始化參數的系統默認值),具體取決於對象大小。
  • METHOD_OPT 是一個 SQL 字符串,用於收集直方圖統計信息。默認值爲 FOR ALL COLUMNS SIZE AUTO。
  • GRANULARITY 是用於爲分區表收集統計信息的粒度。
  • INCREMENTAL 用於以增量方式收集分區表中的全局統計信息。
  • 請注意,您可以使用 DBMS_STATS.SET_PARAM 過程更改上述參數的默認值,這一點很重要。

    注:可以使用 DBA_TAB_STAT_PREFS 視圖說明所有相關表的全部有效統計信息首選項設置。

     

    何時手動收集統計信息

  • 主要依賴自動統計信息收集:
  • –更改自動統計信息收集頻率來滿足您的需要。

    –請記住,應將 STATISTICS_LEVEL 設置爲 TYPICAL 或 ALL,自動統計信息收集功能才能正常運行。

  • 對於下列對象,請手動收集統計信息:
  • –易失對象

    –在批處理操作中修改的對象

    –外部表、系統統計信息、修復的對象

    –在批處理操作中修改的對象:在批處理操作過程中收集統計信息。

    –新建對象:在對象創建之後收集統計信息。

     

    自動統計信息收集機制可使所有統計信息保持爲最新。確定新統計信息的收集時間和收集頻率非常重要。默認的收集間隔是晚上,但是您可以更改此間隔以適應您的業務需要。可以通過更改維護窗口的特徵來達到此目的。但是,在某些情況下可能需要手動收集統計信息。例如,如果白天對錶進行了大幅修改,則表的統計信息可能會過時。這樣的對象一般有兩種類型:

  • 在白天受到大幅修改的易失表
  • 經過大型批量裝載的對象,在兩個統計信息收集間隔之間該對象的總大小增加了 10% 或更多
  • 對於外部表,系統不會在 GATHER_SCHEMA_STATS、GATHER_DATABASE_STATS 和自動優化程序統計信息收集處理期間收集其統計信息。但是,您可以使用 GATHER_TABLE_STATS 收集單個外部表的統計信息。不支持對外部表進行採樣,因此應顯式將 ESTIMATE_PERCENT 選項設置爲空值。因爲不允許對外部表執行數據處理,所以只在相應文件發生更改時分析外部表就足夠了。需要手動收集其中統計信息的其它區域是系統統計信息和修復的對象,如動態性能表。系統不會自動收集這些統計信息。

     

    手動統計信息收集 

    可以使用 Oracle Enterprise Manager 和 DBMS_STATS 程序包來完成以下任務:

  • 生成並管理統計信息,以供優化程序使用:
  • –收集/修改

    –查看/命名

    –導出/導入

    –刪除/鎖定

  • 收集下列項的統計信息:
  • –索引、表、列、分區

    –對象、方案或數據庫

  • 串行或並行收集統計信息
  • 收集/設置系統統計信息(當前在 EM 中尚無法實現)
  • 使用 Oracle Enterprise Manager 和 DBMS_STATS 程序包,都可以爲優化程序手動生成和管理統計信息。可以使用 DBMS_STATS 程序包收集、修改、查看、導出、導入、鎖定和刪除統計信息。還可以使用此程序包標識(或命名)收集的統計信息。您可以按多種粒度收集索引、表、列和分區的統計信息:對象、方案和數據庫級別。

    DBMS_STATS 僅收集優化所需的統計信息,而不收集其它統計信息。例如,DBMS_STATS 收集的表統計信息包括行數、當前包含數據的塊數量和平均行長度,但不包括鏈接行數、平均空閒空間或未使用的數據塊數量。

    注:不要使用 ANALYZE 語句的 COMPUTE 和 ESTIMATE 子句收集優化程序統計信息。僅僅是爲了實現向後兼容才支持這些子句,在以後的版本中可能會將其刪除。DBMS_STATS 程序包可收集更廣泛、更準確的統計信息集,並且收集效率更高。對於與優化程序統計信息收集無關的其它用途,您可以繼續使用 ANALYZE 語句:

  • 使用 VALIDATE 或 LIST CHAINED ROWS 子句
  • 收集空閒列表塊的信息
  •  

    手動統計信息收集:因素

  • 監控 DML 的對象。
  • 確定正確的樣本大小。
  • 確定並行度。
  • 確定是否應使用直方圖。
  • 確定索引的級聯影響。
  • 在 DBMS_STATS 中使用的過程:
  • –GATHER_INDEX_STATS

    –GATHER_TABLE_STATS

    –GATHER_SCHEMA_STATS

    –GATHER_DICTIONARY_STATS

    –GATHER_DATABASE_STATS

    –GATHER_SYSTEM_STATS

     

    手動收集優化程序統計信息時,必須特別注意下列因素:

  • 監控成批數據操縱語言 (DML) 操作的對象,必要時收集統計信息
  • 確定正確的樣本大小
  • 確定並行度以加快對大型對象的查詢速度
  • 確定是否對包含有偏差數據的列創建直方圖
  • 確定對象的更改是否級聯到任何從屬索引
  •  

    管理統計信息收集:示例

     

     

    dbms_stats.gather_table_stats
    ('sh'              -- schema
    ,'customers'       -- table
    , null             -- partition
    , 20               -- sample size(%)
    , false            -- block sample?
    ,'for all columns' -- column spec
    , 4                -- degree of parallelism
    ,'default'       -- granularity 
    , true );          -- cascade to indexes

    dbms_stats.set_param('CASCADE',                  'DBMS_STATS.AUTO_CASCADE');
    dbms_stats.set_param('ESTIMATE_PERCENT','5');
    dbms_stats.set_param('DEGREE','NULL'); 

    第一個示例使用 DBMS_STATS 程序包收集 SH 方案的 CUSTOMERS 表的統計信息。它使用前面幻燈片中討論的某些選項。

    設置參數默認值

    可以使用 DBMS_STATS 中的 SET_PARAM 過程爲所有 DBMS_STATS 過程的參數設置默認值。幻燈片中的第二個示例演示了這種用法。也可以使用 GET_PARAM 函數獲取參數的當前默認值。

    注:只有表是分區表時,才需要考慮要收集的統計信息的粒度。此參數決定應在哪一級別收集統計信息。級別可以是分區、子分區或表。

     

    優化程序動態採樣:概覽

     

  • 對於符合以下特徵的表和索引,可以執行動態採樣:
  • –沒有統計信息

    –其統計信息不可信

  • 在評估時用於確定更準確的統計信息:
  • –表基數

    –謂詞選擇性

  • 此功能由以下項控制:
  • –OPTIMIZER_DYNAMIC_SAMPLING 參數

    –OPTIMIZER_FEATURES_ENABLE 參數

    –DYNAMIC_SAMPLING 提示

    –DYNAMIC_SAMPLING_EST_CDN 提示

     

    動態採樣可確定更準確的選擇性和基數估計值,這樣優化程序便可生成更有效的執行計劃,因而提高了服務器性能。例如,雖然建議您收集所有表的統計信息以供 CBO 使用,但您可能不會收集臨時表和用於臨時數據處理的工作表的統計信息。在此類情況下,CBO 通過一個簡單算法提供一個值,這可能會導致不太理想的執行計劃。可以使用動態採樣完成下列任務:

  • 當收集到的統計信息無法使用或可能會導致重大估計錯誤時,估計單表的謂詞選擇性
  • 爲沒有統計信息的表和相關索引,或者其統計信息太舊已不再可信的表估計表基數
  • 可以使用 OPTIMIZER_DYNAMIC_SAMPLING 初始化參數控制動態採樣。可使用 DYNAMIC_SAMPLING 和 DYNAMIC_SAMPLING_EST_CDN 提示進一步控制動態採樣。

    注:如果設置爲 9.2 之前的版本,OPTIMIZER_FEATURES_ENABLE 初始化參數將關閉動態採樣。

     

    優化程序動態採樣的工作方式

  • 採樣在編譯時完成。
  • 如果查詢受益於動態採樣:
  • –執行遞歸 SQL 語句對數據進行採樣

    –被採樣的塊數量取決於 OPTIMIZER_DYNAMIC_SAMPLING 初始化參數

  • 在動態採樣期間,將對樣本應用謂詞,以確定選擇性。
  • 在以下情況下使用動態採樣:
  • –採樣時間只佔執行時間的一小部分

    –查詢被執行多次

    –您認爲會找到更好的計劃

     

    主要的性能屬性是編譯時間。系統在編譯時將確定查詢是否會從動態採樣受益。如果能從動態採樣受益,則發出遞歸 SQL 語句掃描表塊的一個小型隨機樣本,並應用相關的單個表謂詞估計謂詞選擇性。

    動態採樣查詢會讀取一定數量的塊,具體數量取決於 OPTIMIZER_DYNAMIC_SAMPLING 初始化參數的值。

    對於通常可快速完成的查詢(在不到幾秒鐘的時間內即可完成),您不需要費力地去執行動態採樣。但是,動態採樣在下列任一條件下是有益的:

  • 使用動態採樣可找到更好的計劃。
  • 採樣時間只佔查詢總執行時間的一小部分。
  • 查詢被執行多次。
  • 注:動態採樣可以應用於單個表的謂詞子集,並可與未執行動態採樣的謂詞標準選擇性估計值組合在一起。

     

    OPTIMIZER_DYNAMIC_SAMPLING

     

  • 動態會話或系統參數
  • 可以設置爲 0 到 10 之間的值
  • 值爲 0 時會關閉動態採樣
  • 值爲 1 時對所有未分析的表進行採樣,前提是未分析的表滿足下列條件:
  • –聯接至另一個表,或出現在子查詢或不可合併的視圖中

    –沒有索引

    –包含的塊超過 32 個

  • 值爲 2 時對所有未分析的表進行採樣
  • 值越高,就越積極地應用採樣
  • 如果沒有更新活動,動態採樣可重複進行
  • 可通過將 OPTIMIZER_DYNAMIC_SAMPLING 參數設置爲 0 到 10 之間的值來控制動態採樣。值爲 0 時表示不執行動態採樣。

    值爲 1(默認值)時表示對所有滿足下列條件的未分析的表執行動態採樣:

  • 查詢中至少有一個未分析的表。
  • 此未分析的表聯接至另一個表,或出現在子查詢或不可合併的視圖中。
  • 此未分析的表沒有索引。
  • 此未分析的表包含的塊數多於對此表進行動態採樣可使用的默認塊數。此默認數量
    是 32。
  • 如果 OPTIMIZER_FEATURES_ENABLE 設置爲 10.0.0 或更高,則默認值爲 2。在此級別,系統會對所有未分析的表應用動態採樣。採樣的塊數量是動態採樣的默認塊數量 (32) 的兩倍。

    提高該參數值會導致更積極地應用動態採樣,這表現在採樣的表類型(分析或未分析)以及在採樣上花費的 I/O 量這兩方面。

    注:如果自上次採樣操作後沒有在進行採樣的表中插入、刪除或更新任何行,則動態採樣可重複進行。

     

    鎖定統計信息

     

  • 防止自動收集
  • 主要用於易失表:
  • –不帶統計信息鎖定意味着要進行動態抽樣。

    BEGIN 

      DBMS_STATS.DELETE_TABLE_STATS(‘OE’,’ORDERS’); 

      DBMS_STATS.LOCK_TABLE_STATS(‘OE’,’ORDERS’);

    END;

     

     

    –帶統計信息鎖定可獲得典型值。

    BEGIN

      DBMS_STATS.GATHER_TABLE_STATS(‘OE’,’ORDERS’);

      DBMS_STATS.LOCK_TABLE_STATS(‘OE’,’ORDERS’);

    END;

  • FORCE 參數可覆蓋統計信息鎖定。
  • SELECT stattype_locked FROM dba_tab_statistics;

     

    自 Oracle Database 10g 開始,您可以使用 DBMS_STATS 程序包的 LOCK_TABLE_STATS 過程鎖定指定表的統計信息。可以鎖定沒有統計信息的表的統計信息,或使用 DELETE_*_STATS 過程將其設置爲 NULL,以防止自動收集統計信息,這樣便可以對沒有統計信息的易失表使用動態採樣。易失表填滿時,可以鎖定該表的統計信息,這樣該表的統計信息就會成爲具有代表性的表填充。

    也可以通過使用 LOCK_SCHEMA_STATS 過程在方案級別鎖定統計信息。可以查詢 {USER | ALL | DBA}_TAB_STATISTICS 視圖中的 STATTYPE_LOCKED 列,以確定表的統計信息是否已鎖定。

    可以使用 UNLOCK_TABLE_STATS 過程取消對指定表統計信息的鎖定。

    即使統計信息處於鎖定狀態,也可以將 FORCE 參數的值設置爲 TRUE 來覆蓋它們。FORCE 參數在下列 DBMS_STATS 過程中:DELETE_*_STATS、IMPORT_*_STATS、RESTORE_*_STATS 和 SET_*_STATS。

    注:鎖定表的統計信息後,所有從屬統計信息都被認爲處於鎖定狀態。這包括表統計信息、列統計信息、直方圖和從屬索引統計信息。

     

    來自 <http://www.askmaclean.com/archives/oracle-sql-cbo-%e4%bc%98%e5%8c%96%e5%99%a8%e4%bc%98%e5%8c%96%e7%a8%8b%e5%ba%8f-%e7%bb%9f%e8%ae%a1%e4%bf%a1%e6%81%af.html>

     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章