天天看點

oracle收集統計資訊

什麼是統計資訊

統計資訊主要是描述資料庫中表,索引的大小,規模,資料分布狀況等的一類資訊。比如,表的行數,塊數,平均每行的大小,索引的leaf blocks,索引字段的行數,不同值的大小等,都屬于統計資訊。cbo正是根據這些統計資訊資料,計算出不同通路路徑下,不同join 方式下,各種計劃的成本,最後選擇出成本最小的計劃。

統計資訊是存放在資料字段表中的,如dba_tab_statistics

如何搜集統計資訊

統計資訊搜集也是有多種方法,推薦大家使用dbms_stats 表來進行統計資訊搜集及進行一般的統計資訊維護工作。

dbms-stats 包,主要提供了搜集,删除,導出,導入,修改統計資訊的方法,分别對應于gather系列,delete系列,export 系列,import系列,set系列的子過程。一般可能主要是使用統計資訊的搜集,以及導出導入這樣的功能。具體來說,主要會使用到如下幾個子過程:

gather_index_stats procedure

gathers index statistics.

gather_table_stats procedure

gathers table and column (and index) statistics.

create_stat_table procedure

creates a table with name stattab in ownname's schema which is capable of holding statistics.

export_table_stats procedure

retrieves statistics for a particular table and stores them in the user stat table.

export_schema_stats procedure

retrieves statistics for all objects in the schema identified by ownname and stores them in the user stat table identified by stattab.

import_index_stats procedure

retrieves statistics for a particular index from the user stat table identified by stattab and stores them in the dictionary.

import_table_stats procedure

retrieves statistics for a particular table from the user stat table identified by stattab and stores them in the dictionary.

import_schema_stats procedure

retrieves statistics for all objects in the schema identified by ownname from the user stat table and stores them in the dictionary.

對于統計資訊的搜集,談談個人的幾點了解:

? 統計資訊預設是存放在資料字典表中的,也隻有資料字典中的統計資訊,才會影響到cbo。

? dbms_stats 提供的create_stat_table 過程,隻是生成一個使用者自定義的特定格式的表,用來存放統計資訊罷了,這個表中的統計資訊是不會影響到統計資訊的。

? gather 系列過程中,如果指定stattab,statid,statown 參數(也可以不指定),則是搜集的統計資訊除了更新到資料字典外,還在statown 使用者下的stattab 表中存放一份,标示為 statid;

? export和import 系列的過程中,stattab,statid,statown 參數不能為空,分别表示把資料字典中的目前統計資訊導出到使用者自定義的表中,以及把使用者表中的統計資訊導入到資料字典中,很明顯可以看出,這裡的導入操作和上面gather 操作會改變統計資訊,可能會引起執行執行計劃的改變,是以要慎重操作。

? 每次統計資訊搜集前,将舊的統計資訊備份起來是很有必要的;特别是保留一份或多份系統在穩定時期的統計資訊也是很有必要的。

? 多長時間搜集一次統計資訊,對于統計資訊如何備份和保留,搜集統計資訊時如何選擇合适的采樣,并行,直方圖設定等都比較重要,需要設計一個較好的統計資訊搜集政策。

統計資訊包括下面幾類:

表統計:包括記錄數、block數和記錄平均長度。

列統計:列中不同值的數量(nvd)、空值的數量和資料分布(histogram)。

索引統計:索引葉塊的數量、索引的層數和聚集因子(clustering factor)。

系統統計:i/o性能和使用率和cpu性能和使用率。

生成統計資訊:

統計資訊生成技術包括三種:

基于資料采樣的估計方式

精确計算方式

使用者自定義的統計資訊收集方式

其中采用估算方式可以指定總記錄數的估算百分比或者總塊數的估算百分比。

分區表的統計資訊分為幾級:分區表的整體資訊、分區的統計資訊和子分區的統計資訊。

最常用的收集統計資訊的方式包括:dbms_stats包和analyze語句,oracle推薦使用dbms_stats包來收集統計資訊。

dbms_stats包中用于收集統計資訊的過程包括:

dbms_stats.gather_table_stats  收集表、列和索引的統計資訊;

dbms_stats.gather_schema_stats   收集schema下所有對象的統計資訊;

dbms_stats.gather_index_stats  收集索引的統計資訊;

dbms_stats.gather_system_stats  收集系統統計資訊。

dbms_stats.delete_table_stats  删除表的統計資訊

dbms_stats.export_table_stats 輸出表的統計資訊

dbms_stats.create_state_table

dbms_stats.set_table_stats 設定 表的統計

dbms_stats.auto_sample_size

dbms_stats.gather_database_stats:收集資料庫中所有對象的統計資訊;

在create index和alter index rebuild時可以指定compute statistics語句,對于非分區表重建索引時會收集表、列和索引的統計資訊。對于分區表,隻收集索引資訊,不會收集表和列資訊。

可以在将method_opt參數設定為“for all hidden columns size n”來收集函數索引的索引表達式資訊。

oracle根據下列條件來決定使用哪些索引:

索引中的記錄數;

索引中不同鍵值的數量;

索引的層數;

索引中的葉塊數;

聚集因子;

每個鍵值平均葉塊數;

如果兩個索引的選擇性、查詢代價和集勢都相同,那麼優化器會根據索引名稱的字母順序選

使用analyze指令收集oracle統計資訊

oracle資料庫的pl/sql語句執行的優化器,有基于代價的優化器(cbo)和基于規則的優化器(rbo)。

rbo:依賴于一套嚴格的文法規則,隻要按照規則寫出的語句,不管資料表和索引的内容是否發生變化,不會影響pl/sql語句的"執行計劃"。

cbo:自oracle7版被引入,oracle自7版以來采用的許多新技術都是隻基于cbo的,

如星型連接配接排列查詢,哈希連接配接查詢,反向索引,索引表,分區表和并行查詢等。

cbo計算各種可能"執行計劃"的"代價",即cost,從中選用cost最低的方案,作為實際運作方案。

各"執行計劃"的cost的計算根據,依賴于資料表中資料的統計分布,oracle資料庫本身對該統計分布是不清楚的,

須要分析表和相關的索引,才能搜集到cbo所需的資料。

cbo是oracle推薦使用的優化方式,要想使用好cbo,使sql語句發揮最大效能,必須保證統計資料的及時性。

統計資訊的生成可以有完全計算法和抽樣估算法。sql例句如下:

完全計算法: analyze table abc compute statistics;

抽樣估算法(抽樣20%): analyze table abc estimate statistics sample 20 percent;

對表作完全計算所花的時間相當于做全表掃描,抽樣估算法由于采用抽樣,比完全計算法的生成統計速度要快,如果不是要求要有精确資料的話,盡量采用抽樣分析法。

建議對表分析采用抽樣估算,對索引分析可以采用完全計算。

我們可以采用以下兩種方法,對資料庫的表和索引及簇表定期分析生成統計資訊,保證應用的正常性能。

1. 在系統設定定時任務,執行分析腳本。

在資料庫伺服器端,我們以unix使用者oracle,運作腳本analyze,在analyze中,我們生成待執行sql腳本,并運作。(假設我們要分析scott使用者下的所有表和索引)

analyze腳本内容如下:

sqlplus scott/tiger << eof

    set pagesize 5000

    set heading off

    spool analytab.sql

    select "analyze table scott."||table_name||" estimate statistics sample 20 percent ;" from user_tables;

    spool off

    spool analyind.sql

    select "analyze table scott."||table_name||" estimate statistics sample 20 percent for all indexes;" from user_tables;

    spool analyze.log

    @analytab.sql

    @analyind.sql

    exit

在unix平台上crontab加入,以上檔案,設定為每個月或合适的時間段運作。

或者将如下腳本儲存成analyze.sql,然後在sqlplus裡面執行:

set pagesize 5000

set linesize 300

set trims on

set heading off

set feedback off

spool analytab.sql

select 'analyze table zfmi.'||table_name||' compute statistics ;'

from user_tables;

spool off

spool analyidx.sql

select 'analyze table zfmi.'||table_name||' compute statistics

for all indexes;' from user_tables;

spool analylog.log

@@analytab.sql

@@analyidx.sql

2. 利用oracle提供的程式包(package)對相關的資料庫對象進行分析。

    有以下的程式包可以對表,索引,簇表進行分析。

    包中的存儲過程的相關參數解釋如下:

    type可以是:table,index,cluster中其一。

    schema為:table,index,cluster的所有者,null為目前使用者。

    name為:相關對象的名稱。

    method是:estimate,compute,delete中其一,當選用estimate,

    下面兩項,estimate_rows和estimate_percent不能同時為空值。

    estimate_rows是:估算的抽樣行數。

    estimate_percent是:估算的抽樣百分比。

   當estimate_percent參數是手動指定的,如果手動指定的參數過小,不能收集到足夠的資訊,那麼dbms_stats可能會自動增長estimate_percent的值,這樣就能確定收集到足夠的統計資訊。

控制采樣的參數是estimate_percent,采樣的參數可以設定任意值(當然要在範圍内),不過oracle公司推薦設定estimate_percent為dbms_stats.auto_sample_size。

auto_sample_sile可以讓oracle自己決定最好的采樣值,因為不同類型(table,index,column)的統計資訊有不同的需求。

    method_opt是:有以下選項,

    for table /*隻統計表*/

    [for all [indexed] columns] [size n] /*隻統計有索引的表列*/

    for all indexes /*隻分析統計相關索引*/

    參數method_opt控制柱狀圖的收集。oracle公司推薦設定method_opt為for all columns size auto。這樣設定過後oracle會自動的判斷哪一列需要收集柱狀圖,并且自動的設定柱狀圖

    的bucket。你同樣可以手動的設定哪一列需要收集柱狀圖,以及柱狀圖的bucket。

    partname是:指定要分析的分區名稱。

    degree:控制dbms_stats是否使用并行特征。

    oracle公司推薦将degree參數設定為dbms_stats.auto_degree。這樣設定過後,oracle就能夠根據object的size,以及與并行有關的init參數來決定一個恰當的并行度

    收集統計資訊。注意:cluster index,domain index,bitmap join index不能使用并行特征。

補充

    對于分區表和分區索引,dbms_stats既可以單獨的收集分區統計資訊,也可以收集整個表/索引的統計資訊。對于組合分區,dbms_stats也能夠收集子分區,分區,以及整個表/索引的統計資訊。參數granularity控制分區統計資訊的收集。因為分區統計資訊,全局統計資訊對于大多數系統來說都是非常重要的,是以oracle公司推薦将其設定為auto來收集分區,以及全局的統計資訊。

當對表收集統計資訊的時候,dbms_stats會收集列的資料分布資訊。資料分布最基本的統計資訊就是這個列的最大值與最小值。如果這一列是傾斜的,那麼優化器僅僅根據列最大值與最小值是無法制定出準确的執行計劃的。對于傾斜的資料分布,我們可以收集列的直方圖/柱狀圖統計資訊,這樣可以讓優化器制定出更加準确的執行計劃。

為了知道統計資訊是否過期,oracle提供了表監控功能。将init參數statistics_level設定為all或者typical(預設),就開啟了表監控的功能(10g已經不需要alter table monitor了)。表監控功能跟蹤表的insert,update,delete,truncate,操作,并且記錄在dba_tab_modifications視圖裡面。

我們在查詢dba_tab_modifications視圖的時候有可能查詢不到結果,或者查詢的結果不準确,這個時候需要用dbms_stats.flush_database_monitoring_info過程将記憶體中的資訊重新整理到該視圖中。

options參數設定為gather stale或者gather auto,就會讓dbms_stats判斷表的統計資訊是否過期

(注意gather_table_stats中沒有這個參數,隻有gather_database_stats,gather_schema_stats過程中有這個參數)。

判斷表的統計資訊是否過期的依據是是否有10%以上的資料被修改過,如果被修改過了,那麼oracle就認為之前的統計資訊過期了,oracle會重新收集統計資訊。

在我們建立了函數索引之後,我們要為列收集統計資訊,這個時候我們需要設定參數method_opt為for all hidden columns。

例子

    1)

    dbms_ddl.analyze_object(

    type varchar2,

    schema varchar2,

    name varchar2,

    method varchar2,

    estimate_rows number default null,

    estimate_percent number default null,

    method_opt varchar2 default null,

    partname varchar2 default null ) ;

    該存儲過程可對特定的表,索引和簇表進行分析。例如,對scott使用者的emp表,進行50%的抽樣分析,參數如下:

    dbms_ddl.analyze_object("table", "scott", "emp", "estimate", null,50);

    2)

    dbms_utility.analyze_schema (

    method_opt varchar2 default null ) ;

    dbms_utility.analyze_database (

    method_opt varchar2 default null );

    其中,analyze_schema用于對某個使用者擁有的所有table,index和cluster的分析統計。analyze_database用于對整個資料庫進行分析統計。

    3) dbms_stats是在oracle8i中新增的程式包,它使統計資料的生成和處理更加靈活友善,并且可以并行方式生成統計資料。在程式包中的以下過程分别分析統計table,index,schema,database級别的資訊。

    dbms_stats.gather_table_stats

    dbms_stats.gather_index_stats

    dbms_stats.gather_schema_stats

    dbms_stats.gather_database_stats

    在這裡,我們以資料庫job的方式,定時對資料庫中scott模式下所有的表和索引進行分析:

    在sql*plus下運作:

    variable jobno number;

    begin

    dbms_jobs.submit ( :jobno ,

    " dbms_utility.analyze_schema ( "scott", "estimate", null, 20) ; ",

    sysdate, "sysdate+30");

    commit;

    end;

    /

    statement processed.

    print jobno

    jobno

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

    16

    以上作業,每隔一個月用dbms_utility.analyze_schema對使用者scott的所有表,簇表和索引作統計分析。

收集統計資訊的政策

通常情況下,我們會将oracle自動收集統計資訊功能給關閉,我們會采用手動的方式給資料庫收集統計資訊。至于收集統計資訊的政策需要根據系統來确定。下面說說幾種常見的情況:

如果你系統中的表的資料是增量(有規律)的增加,也就是說你幾乎不做任何的批量處理操作,比如批量删除,批量加載操作。對于這樣的表收集統計資訊是非常簡單的。你可以通過檢視dba_tab_modifications視圖來觀察表的變化情況,觀察表中資料量的變化是否超過了10%,并且記錄下天數。這樣你就可以每隔這樣的時間間隔對其收集一次統計資訊。你可以用crontab,或者job調用gather_schema_stats或者gather_table_stats過程來收集統計資訊。

對于經常批量操作的表,那麼表的統計資訊就必須在批量操作之後對其收集統計資訊。

對于分區表,通常隻有一個分區被修改,這種情況下可以隻收集單獨分區的統計資訊,不過收集整個表的統計資訊還是非常有必要的。