天天看點

Oracle RBO、CBO簡介

Rule Based Optimizer(RBO)基于規則

Cost Based Optimizer(CBO)基于成本,或者講統計資訊

ORACLE 提供了CBO、RBO兩種SQL優化器。CBO在ORACLE7 引入,但在ORACLE8i 中才成熟。ORACLE 已經明确聲明在ORACLE9i之後的版本中(ORACLE 10G ),RBO将不再支援。是以選擇CBO 是必然的趨勢。

CBO和 RBO作為不同的SQL優化器,對SQL語句的執行計劃産生重大影響,如果要對現有的應用程式從RBO向CBO移植,則必須充分考慮這些影響,避免SQL語句性能急劇下降;但是,對新的應用系統,則可以考慮直接使用CBO,在CBO模式下進行SQL語句編寫、分析執行計劃、性能測試等工作,這需要開發者對CBO的特性比較熟悉。以下小結幾點在CBO下寫SQL語句的注意事項:

1、RBO自ORACLE 6版以來被采用,有着一套嚴格的使用規則,隻要你按照它去寫SQL語句,無論資料表中的内容怎樣,也不會影響到你的“執行計劃”,也就是說對資料不“敏感”;CBO計算各種可能“執行計劃”的“代價”,即cost,從中選用cost最低的方案,作為實際運作方案。各“執行計劃”的cost的計算根據,依賴于資料表中資料的統計分布,ORACLE資料庫本身對該統計分布并不清楚,必須要分析表和相關的索引(使用ANALYZE 指令),才能搜集到CBO所需的資料。

2、使用CBO 時,編寫SQL語句時,不必考慮"FROM" 子句後面的表或視圖的順序和"WHERE" 子句後面的條件順序;ORACLE自7版以來采用的許多新技術都是基于CBO的,如星型連接配接排列查詢,哈希連接配接查詢,函數索引,和并行查詢等。

3、一般而言,CBO所選擇的“執行計劃”都不會比RBO的“執行計劃”差,而且相對而言,CBO對程式員的要求沒有RBO那麼苛刻,節省了程式員為了從多個可能的“執行計劃”中選擇一個最優的方案而花費的調試時間,但在某些場合下也會存在問題。較典型的問題有:有時,表明明建有索引,但查詢過程顯然沒有用到相關的索引,導緻查詢過程耗時漫長,占用資源巨大,這時就需要仔細分析執行計劃,找出原因。例如,可以看連接配接順序是否允許使用相關索引。假設表emp的deptno列上有索引,表dept的列deptno上無索引,WHERE語句有emp.deptno=dept.deptno條件。在做NL連接配接時,emp做為外表,先被通路,由于連接配接機制原因,外表的資料通路方式是全表掃描,emp.deptno上的索引顯然是用不上,最多在其上做索引全掃描或索引快速全掃描。

4、如果一個語句使用 RBO的執行計劃确實比CBO 好,則可以通過加 " rule" 提示,強制使用RBO。

5、使用CBO 時,SQL語句 "FROM" 子句後面的表,必須全部使用ANALYZE 指令分析過,如果"FROM" 子句後面的是視圖,則此視圖的基礎表,也必須全部使用ANALYZE 指令分析過;否則,ORACLE 會在執行此SQL語句之前,自動進行ANALYZE 指令分析,這會極大導緻SQL語句執行極其緩慢。

6、使用CBO 時,SQL語句 "FROM" 子句後面的表的個數不宜太多,因為CBO在選擇表連接配接順序時,會對"FROM" 子句後面的表進行階乘運算,選擇最好的一個連接配接順序。假如"FROM" 子句後有6個表,則其可選擇的連接配接順序就是6*5*4*3*2*1 = 720 種,CBO 選擇其中一種,而如果"FROM" 子句後有12個表,則其可選擇的連接配接順序就是12*11*10*9*8*7*6*5*4*3*2*1= 479001600 種,可以想象從中選擇一種,會消耗多少CPU 時間?如果實在是要通路很多表,則最好使用 ORDER 提示,強制使用"FROM" 子句表固定的通路順序。

7、使用CBO 時,SQL語句中不能引用系統資料字典表或視圖,因為系統資料字典表都未被分析過,可能導緻極差的“執行計劃”。但是不要擅自對資料字典表做分析,否則可能導緻死鎖,或系統性能嚴重下降。

8、使用CBO 時,要注意看采用了哪種類型的表連接配接方式。ORACLE的共有Sort Merge Join(SMJ)、Hash Join(HJ)和Nested Loop Join(NL)。CBO有時會偏重于SMJ 和 HJ,但在OLTP 系統中,NL 一般會更好,因為它高效的使用了索引。在兩張表連接配接,且内表的目标列上建有索引時,隻有Nested Loop才能有效地利用到該索引。SMJ即使相關列上建有索引,最多隻能因索引的存在,避免資料排序過程。HJ由于須做HASH運算,索引的存在對資料查詢速度幾乎沒有影響。

9、使用CBO 時,必須保證為表和相關的索引搜集足夠的統計資料。對資料經常有增、删、改的表最好定期對表和索引進行分析,可用SQL語句“analyze table xxx compute statistics for all indexes;"ORACLE掌握了充分反映實際的統計資料,才有可能做出正确的選擇。

10、使用CBO 時,要注意被索引的字段的值的資料分布,會影響SQL語句的執行計劃。例如:表emp,共有一百萬行資料,但其中的emp.deptno列,資料隻有4種不同的值,如10、20、30、40。雖然emp資料行有很多,ORACLE預設認定表中列的值是在所有資料行均勻分布的,也就是說每種deptno值各有25萬資料行與之對應。假設SQL搜尋條件DEPTNO=10,利用deptno列上的索引進行資料搜尋效率,往往不比全表掃描的高,ORACLE理所當然對索引“視而不見”,認為該索引的選擇性不高。

我們考慮另一種情況,如果一百萬資料行實際不是在4種deptno值間平均配置設定,其中有99萬行對應着值10,5000行對應值20,3000行對應值30,2000行對應值40。在這種資料分布圖案中對除值為10外的其它deptno值搜尋時,毫無疑問,如果索引能被應用,那麼效率會高出很多。我們可以采用對該索引列進行單獨分析,或用analyze語句對該列建立直方圖,對該列搜集足夠的統計資料,使ORACLE在搜尋選擇性較高的值能用上索引。