優化器(Optermizer)

轉自:http://hi.baidu.com/nsj820/blog/item/cb7a5d0ed1183cc07acbe12b.html

一、優化器的優化方式 
        Oracle的優化器共有兩種的優化方式,即基於規則的優化方式(Rule-BasedOptimization,簡稱爲RBO)和基於代價的優化方式(Cost-BasedOptimization,簡稱爲CBO) 
        1CBO方式:依詞義可知,它是看語句的代價(Cost)了,這裏的代價主要指Cpu和內存。優化器在判斷是否用這種方式時,主要參照的是表及索引的統計信息。統計信息給出表的大小、有少行、每行的長度等信息。這些統計信息起初在庫內是沒有的,是你在做analyze後纔出現的,很多的時侯過期統計信息會令優化器做出一個錯誤的執行計劃,因些我們應及時更新這些信息。在Oracle8及以後的版本,Oracle列推薦用CBO的方式。 
        2RBO方式:優化器在分析SQL語句時,所遵循的是Oracle內部預定的一些規則。比如我們常見的,當一個where子句中的一列有索引時去走索引。 
       我們要明瞭,不一定走索引就是優的 ,比如一個表只有兩行數據,一次IO就可以完成全表的檢索,而此時走索引時則需要兩次IO,這時對這個表做全表掃描(full tablescan)是最好的。 
二、優化器的優化模式(Optermizer Mode) 
   
優化模式包括Rule,Choose,First rows,All rows這四種方式: 
        Rule:不用多說,即走基於規則的方式。 
        Choolse:默認的情況下Oracle用的便是這種方式。指的是當一個表或或索引有統計信息,則走CBO的方式,如果表或索引沒統計信息,表又不是特別的小,而且相應的列有索引時,那麼就走索引,RBO的方式。 
        First Rows
:它與Choose方式是類似的,所不同的是當一個表有統計信息時,它將是以最快的方式返回查詢的最先的幾行,從總體上減少了響應時間。 
        All Rows:也就是我們所說的Cost的方式,當一個表有統計信息時,它將以最快的方式返回表的所有的行,從總體上提高查詢的吞吐量。沒有統計信息則走基於規則的方式。
三、如何設定選用哪種優化模式 
        1Sessions級別
 
       
通過SQL> ALTER SESSION SET OPTIMIZER_MODE=?;來設定。 
        2Instance級別 
       
我們可以通過在init.ora文件中設定OPTIMIZER_MODE=RULE、OPTIMIZER_MODE=CHOOSE、OPTIMIZER_MODE=FIRST_ROWS、OPTIMIZER_MODE=ALL_ROWS去選用以上所提的四種方式,如果你沒設定OPTIMIZER_MODE參數則默認用的是Choose這種方式。 
        3、語句級別 
       
這些需要用到Hint,比如: 

SELECT /*+ RULE */ a.userid,b.name,b.depart_name FROM tf_f_yhda a,tf_f_depart bWHERE a.userid=b.userid; 
四、與CBO相關統計信息的獲取(analyze  dbms_stats 使用)
    壹、analyze 使用
        1、功能

       a)蒐集和刪除索引、表和簇的統計信息
       b)驗證表、索引和簇的結構
       c)鑑定表和簇和行遷移和行聯接
       d)針對analyze的蒐集和刪除統計信息功能而言,oracle推薦使用DBMS_STATS包來蒐集優化信息,DBMS_STATS可以並行的蒐集信息,可以蒐集分區表的全局信息,進一步來說,按成本的優化器只會使用DBMS_STATS包所統計出來的信息。
        2、可供分析的對象
               INDEX
對索引進行分析,分析的結果會放在USER_INDEXES,ALL_INDEXES,或 DBA_INDEXES中
       分析的內容:
Depthof the index from its root block to its leaf blocks (BLEVEL) 
Number of leaf blocks (LEAF_BLOCKS) 
Number of distinct index values (DISTINCT_KEYS) 
Average number of leaf blocks for each index value(AVG_LEAF_BLOCKS_PER_KEY) 
Average number of data blocks for each index value (for an index on a table)(AVG_DATA_BLOCKS_PER_KEY) 
Clustering factor (how well ordered the rows are about the indexed values)(CLUSTERING_FACTOR)
               TABLE對錶進行分析,分析的結果會放在USER_TABLES,ALL_TABLES, and DBA_TABLES表中,在分析表的時候,oracle也會分析基於函數的index所引用的表達式
       分析的內容:
Numberof rows (NUM_ROWS)
Number of data blocks below the high water mark (that is, the number of datablocks that have been formatted to receive data, regardless whether theycurrently contain data or are empty) (BLOCKS) 
Number of data blocks allocated to the table that have never been used(EMPTY_BLOCKS) Average available free space in each data block in bytes(AVG_SPACE) 
Number of chained rows (CHAIN_COUNT) Average row length, including the row'soverhead, in bytes (AVG_ROW_LEN)
               PARTITION | SUBPARTITION:對分區表或索引進行分析
               CLUSTER:對簇進行分析,分析的結果會放在ALL_CLUSTERS, USER_CLUSTERS and DBA_CLUSTERS.
        compute_statistics_clause
       語法:

COMPUTE [ SYSTEM ] STATISTICS [for_clause]
        對分析對像進行精確的統計,然後把信息存儲的數據字典中。可以選擇對錶或對字段進行分析。
       computed和estimated這兩種方式的統計數據都被優化器用來影響sql的執行計劃 
        如果指定system選項就只統計系統產生的信息[for_clause]

        FOR TABLE:只統計表 

        FOR COLUMNS:只統計某個字段 

        FOR ALL COLUMNS:統計所有字段 

        FOR ALLINDEXED COLUMNS:統計索引的所有字段
        estimate_statistics_clause

ESTIMATE [ SYSTEM ] STATISTICS [for_clause][SAMPLE integer { ROWS |PERCENT }]
        只是對部分行做一個大概的統計。適用於大表
       SAMPLE:指定具體統計多少行,如果忽略這個參數的話,oracle會默認爲1064行
       ROWS causes:行數 Oracle to sample integer rows of the table or cluster orinteger entries from the index. The integer must be at least 1. 
       PERCENT causes
:百分數
       validation_clauses
      
分析REF或是對像的結構   EG

ANALYZE TABLE employees VALIDATE STRUCTURE CASCADE;
ANALYZE TABLE customers VALIDATE REF UPDATE;
        3、分析表的限制
               a)不可以分析數據字典表
               b)不可以分析擴展表,但可以用DBMS_STATS來實現這個目的
               c)不可以分析臨時表
               d)不可以計算或估計下列字段類型REFs,varrays, nested tables, LOBs (LOBs are not analyzed, they are skipped), LONGs,or object types.
   貳、dbms_stats 使用
       Dbms_stats是oracle8i新增的程序包,它使統計數據的生成和處理更加方便。

--參數
       estimate_percent       --估算抽樣百分比 
       method_opt fortable    --只統計表 
       for all indexed columns --只統計有索引的表列 
       for allindexes         --只分析統計相關索引
--創建統計信息歷史保留表

sql>exec dbms_stats.create_stat_table(ownname => 'scott',stattab =>'stat_table') ;
pl/sql procedure successfully completed
--導出整個scheme的統計信息
sql>exec dbms_stats.export_schema_stats(ownname => 'scott',stattab =>'stat_table') ;
pl/sql procedure successfully completed
--分析scheme
Exec dbms_stats.gather_schema_stats( 
ownname => 'scott', 
options => 'GATHER AUTO', 
estimate_percent => dbms_stats.auto_sample_size, 
method_opt => 'for all indexed columns ', 
degree => 6 )
--分析表
sql>exec dbms_stats.gather_table_stats(ownname => 'scott',tabname =>'work_list',estimate_percent => 10,method_opt=> 'for all indexedcolumns') ;
pl/sql procedure successfully completed
--分析索引
SQL>exec dbms_stats.gather_index_stats(ownname => 'crm2',indname =>'IDX_ADM_PERMISSION_PID_MID',estimate_percent => '10',degree => '4') ;
pl/sql procedure successfully completed
--如果發現執行計劃走錯,刪除表的統計信息
SQL>dbms_stats.delete_table_stats(ownname=> 'scott',tabname => 'work_list') ;
pl/sql procedure successfully completed
--導入錶的歷史統計信息
sql>exec dbms_stats.import_table_stats(ownname => 'scott',tabname =>'work_list',stattab => 'stat_table') ;
pl/sql procedure successfully completed
--如果進行分析後,大部分表的執行計劃都走錯,需要導回整個scheme的統計信息
sql>exec dbms_stats.import_schema_stats(ownname => 'scott',stattab =>'stat_table');
pl/sql procedure successfully completed
--導入索引的統計信息
SQL>exec dbms_stats.import_index_stats(ownname => 'crm2',indname =>'IDX_ADM_PERMISSION_PID_MID',stattab => 'stat_table')
--檢查是否導入成功
SQL>select table_name,num_rows,a.blocks,a.last_analyzed from all_tables a wherea.table_name='WORK_LIST';
TABLE_NAME NUM_ROWS BLOCKS LAST_ANALYZED
------------------------------ ---------- ---------- -------------
WORK_LIST 4005 186 2007-10-12 15
    叄、analyze dbms_stats 區別
      自從Oracle8.1.5引入dbms_stats包,Experts們便推薦使用dbms_stats取代analyze。理由如下
       1,dbms_stats可以並行分析 
       2,dbms_stats有自動分析的功能(alter tablemonitor ) 
       3,analyze 分析統計信息的不準確some times
      如果想分析整個用戶或數據庫,還可以採用工具包,可以並行分析:Dbms_utility(8i以前的工具包) Dbms_stats(8i以後提供的工具包),如:(以下兩個dbms_stats最常用)
dbms_stats.gather_schema_stats(User,estimate_percent=>100,cascade=>TRUE);
dbms_stats.gather_table_stats(User,TableName,degree =>4,cascade => true); 
   總結:
       1DBMS_STATS的優點
      
a) 可以並行進行,對多個用戶,多個Table
       b) 可以得到整個分區表的數據和單個分區的數據。
       c) 可以在不同級別上ComputeStatistics:單個分區,子分區,全表,所有分區
       d) 可以倒出統計信息
       e) 可以用戶自動收集統計信息
       f) 對於分區表,建議使用DBMS_STATS,而不是使用Analyze語句
       g) 對於oracle 9裏面的External Table,Analyze不能使用,只能使用DBMS_STATS來收集信息
       2DBMS_STATS的缺點
      
a) 不能Validate Structure
       b) 不能收集CHAINEDROWS, 不能收集CLUSTER TABLE的信息,這兩個仍舊需要使用Analyze語句
       c) DBMS_STATS 默認不對索引進行Analyze,因爲默認Cascade是False,需要手工指定爲True
五、應用一例:
  1、按用戶分析
BEGIN
DBMS_STATS.GATHER_SCHEMA_STATS(OWNNAME=> 'SCOTT' , CASCADE=> TRUE);
END ;
  2、單表分析
ANALYZE TABLE MYTABLE COMPUTE STATISTICS;
獲取分析語句:
SELECT 'ANALYZE TABLE '||TABLE_NAME||' COMPUTE STATISTICS;' FROM USER_TABLES; 
  3、用途舉例:
select a.table_name, a.num_rows from user_tables a where a.num_rows = 0;
--統計記錄數據爲空的表,如果事先未進行數據分析,則統計結果可能會不正確 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章