ORACLE優化器的優化方式有兩大類,即基於規則的優化方式(Rule-Based Optimization,簡稱為RBO)和基於代價的優化方式(Cost-Based Optimization,簡稱為CBO)。 A、 RBO方式:優化器在分析SQL語句時,更據數據庫中表和索引等定義信息,遵循的是Oracle內部預定的一些規則。比如我們常見的:當一個where子句中的一列有索引時去走索引而不走全表掃描。 B、 CBO方式:依詞義可知,它是看語句的代價(Cost)了。基於代價的查詢,數據庫根據搜集的表和索引的數據的統計信息(統計信息通過analyze 命令或者使用dbms_stats包來搜集)綜合來決定選取一個數據庫認為最優的執行計划(實際上不一定最優) 。統計信息給出表的大小 、有多少行、每行的長度等信息。 注意:這些統計信息起初在庫內是沒有的,是根據 analyze 命令或者dbms_stats包來定期搜集后才出現的,所以很多的時侯過期統計信息會令優化器做出一個錯誤的執行計划,因些我們應及時更新這些信息。為了使用基於成本的優化器(CBO) , 你必須經常運行analyze或dbms_stats命令,以增加數據庫中的對象統計信息(object statistics)的准確性。 在Oracle8及以后的版本,Oracle強列推薦用CBO的方式。 1. 如何查看對象統計信息(object statistics) 對CBO模式,對象統計信息至關重要。如何查看對象統計信息(object statistics)? Oracle中關於表的統計信息是在數據字典中的,可以下SQL查詢到,eg: SELECT table_name,num_rows, blocks, empty_blocks AS empty, avg_space, chain_cnt, avg_row_len FROM dba_tables WHERE owner = ‘ONT’ AND table_name = ‘OE_ORDER_LINES_ALL’; TABLE_NAME NUM_ROWS BLOCKS EMPTY AVG_SPACE CHAIN_CNT AVG_ROW_LEN OE_ORDER_LINES_ALL 5344 505 5 0 0 441 可以看到數據字典中統計到的該表有5344筆記錄,我們下SQL驗證一下: select count(*) from apps.OE_ORDER_LINES_ALL; 發現返回是16518筆記錄,可見這個表的統計信息是比較陳舊的,真實數據與統計到的數據有較大的差別。在這種情況下,如果某個View用到此Table,且系統使用CBO的方式,則可能導致Oracle的optimizer給出效率低下的執行計划。 此時可以用ANALYZE去重新統計OE_ORDER_LINES_ALL這個表,可以下SQL: ANALYZE TABLE ONT.OE_ORDER_LINES_ALL COMPUTE STATISTICS; 再次Query數據字典: TABLE_NAME NUM_ROWS BLOCKS EMPTY AVG_SPACE CHAIN_CNT AVG_ROW_LEN OE_ORDER_LINES_ALL 16518 1530 1035 865 257 643 發現此時的信息已是最新的了。有了比較正確的統計信息,optimizer才能給出高效的執行計划。 2. 並發請求: 統計數據收集模式(FNDGSCST) / Gather Schema Statistics Oracle ERP中有幾個與Gather有關的標准Request: Gather All Column Statistics –FND_STATS.GATHER_ALL_COLUMN_STATS() Gather Column Statistics –FND_STATS.GATHER_COLUMN_STATS() Gather Schema Statistics –FND_STATS.GATHER_SCHEMA_STATS() Gather Table Statistics –FND_STATS.GATHER_TABLE_STATS() 查看FND_STATS 這個Package的寫法,其實它就是在調用Oracle DB中Standard的Package dbms_stats 中的某些Function。 Oracle DB中常用的Gather有以下一些,DBA也可以直接在Database級別上定期Run這些Function,以便能讓Oracle統計到最新的數據庫狀況: dbms_stats.gather_database_stats(); dbms_stats.gather_schema_stats(); dbms_stats.gather_table_stats(); dbms_stats.gather_index_stats(); Oracle CBO需要系統定期分析統計表/索引。 只有這樣CBO才能使用正確的SQL訪問路徑,提高查詢效率。 因此在Instance Level的optimizer_mode = choose ,定期運行ANALYZE 或dbms_stats是非常重要的,尤其是當上次統計后,數據量已發生較大變化之后。 注意:統計操作是很耗資源的動作,要在系統Loading小的時候進行。
