ORACLE優化器RBO與CBO介紹總結
RBO和CBO的基本概念
Oracle資料庫中的優化器又叫查詢優化器(Query Optimizer)。它是SQL分析和執行的優化工具,它負責生成、制定SQL的執行計劃。Oracle的優化器有兩種,基於規則的優化器(RBO)與基於代價的優化器(CBO)
RBO: Rule-Based Optimization 基於規則的優化器
CBO: Cost-Based Optimization 基於代價的優化器
RBO自ORACLE 6以來被採用,一直沿用至ORACLE 9i. ORACLE 10g開始,ORACLE已經徹底丟棄了RBO,它有著一套嚴格的使用規則,只要你按照它去寫SQL語句,無論資料表中的內容怎樣,也不會影響到你的“執行計劃”,也就是說RBO對資料不“敏感”;它根據ORACLE指定的優先順序規則,對指定的表進行執行計劃的選擇。比如在規則中,索引的優先順序大於全表掃描;RBO是根據可用的訪問路徑以及訪問路徑等級來選擇執行計劃,在RBO中,SQL的寫法往往會影響執行計劃,它要求開發人員非常瞭解RBO的各項細則,菜鳥寫出來的SQL指令碼效能可能非常差。隨著RBO的被遺棄,漸漸不為人所知。也許只有老一輩的DBA對其瞭解得比較深入。關於RBO的訪問路徑,官方文件做了詳細介紹:
RBO Path 1: Single Row by Rowid
RBO Path 2: Single Row by Cluster Join
RBO Path 3: Single Row by Hash Cluster Key with Unique or Primary Key
RBO Path 4: Single Row by Unique or Primary Key
RBO Path 7: Indexed Cluster Key
RBO Path 9: Single-Column Indexes
RBO Path 10: Bounded Range Search on Indexed Columns
RBO Path 11: Unbounded Range Search on Indexed Columns
RBO Path 13: MAX or MIN of Indexed Column
RBO Path 14: ORDER BY on Indexed Column
CBO是一種比RBO更加合理、可靠的優化器,它是從ORACLE 8中開始引入,但到ORACLE 9i 中才逐漸成熟,在ORACLE 10g中完全取代RBO, CBO是計算各種可能“執行計劃”的“代價”,即COST,從中選用COST最低的執行方案,作為實際執行方案。它依賴資料庫物件的統計資訊,統計資訊的準確與否會影響CBO做出最優的選擇。如果對一次執行SQL時發現涉及物件(表、索引等)沒有被分析、統計過,那麼ORACLE會採用一種叫做動態取樣的技術,動態的收集表和索引上的一些資料資訊。
關於RBO與CBO,我有個形象的比喻:大資料時代到來以前,做生意或許憑藉多年累計下來的經驗(RBO)就能夠很好的做出決策,跟隨市場變化。但是大資料時代,如果做生意還是靠以前憑經驗做決策,而不是靠大資料、資料分析、資料探勘做決策,那麼就有可能做出錯誤的決策。這也就是越來越多的公司對BI、資料探勘越來越重視的緣故,像電商、遊戲、電信等行業都已經大規模的應用,以前在一家遊戲公司資料庫部門做BI分析,挖掘潛在消費使用者簡直無所不及。至今映像頗深。
CBO與RBO的優劣
CBO優於RBO是因為RBO是一種呆板、過時的優化器,它只認規則,對資料不敏感。畢竟規則是死的,資料是變化的,這樣生成的執行計劃往往是不可靠的,不是最優的,CBO由於RBO可以從很多方面體現。下面請看一個例子,此案例來自於《讓Oracle跑得更快》。
SQL> create table test as select 1 id ,object_name from dba_objects;
Table created.
SQL> create index idx_test on test(id);
Index created.
SQL> update test set id=100 where rownum =1;
1 row updated.
SQL> select id, count(1) from test group by id;
ID COUNT(1)
---------- ----------
100 1
1 50314
從上面可以看出,該測試表的資料分佈極其不均衡,ID=100的記錄只有一條,而ID=1的記錄有50314條。我們先看看RBO下兩條SQL的執行計劃.
SQL> select /*+ rule */ * from test where id =100;
Execution Plan
----------------------------------------------------------
Plan hash value: 2473784974
------------------------------------------------
| Id | Operation | Name |
------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST |
|* 2 | INDEX RANGE SCAN | IDX_TEST |
------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=100)
Note
-----
- rule based optimizer used (consider using cbo)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
588 bytes sent via SQL*Net to client
469 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
SQL> select /*+ rule */ * from test where id=1;
50314 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 2473784974
------------------------------------------------
| Id | Operation | Name |
------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST |
|* 2 | INDEX RANGE SCAN | IDX_TEST |
------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=1)
Note
-----
- rule based optimizer used (consider using cbo)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
7012 consistent gets
97 physical reads
0 redo size
2243353 bytes sent via SQL*Net to client
37363 bytes received via SQL*Net from client
3356 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
50314 rows processed
從執行計劃可以看出,RBO的執行計劃讓人有點失望,對於ID=1,幾乎所有的資料全部符合謂詞條件,走索引只能增加額外的開銷(因為ORACLE首先要訪問索引資料塊,在索引上找到了對應的鍵值,然後按照鍵值上的ROWID再去訪問表中相應資料),既然我們幾乎要訪問所有表中的資料,那麼全表掃描自然是最優的選擇。而RBO選擇了錯誤的執行計劃。可以對比一下CBO下SQL的執行計劃,顯然它對資料敏感,執行計劃及時的根據資料量做了調整,當查詢條件為1時,它走全表掃描;當查詢條件為100時,它走區間索引掃描。如下所示:
SQL> select * from test where id=1;
50314 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 49075 | 3786K| 52 (2)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TEST | 49075 | 3786K| 52 (2)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("ID"=1)
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------
32 recursive calls
0 db block gets
3644 consistent gets
0 physical reads
0 redo size
1689175 bytes sent via SQL*Net to client
37363 bytes received via SQL*Net from client
3356 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
50314 rows processed
SQL> select * from test where id =100;
Execution Plan
----------------------------------------------------------
Plan hash value: 2473784974
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 79 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST | 1 | 79 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_TEST | 1 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=100)
Note
-----
- dynamic sampling used for this statement
Statistics
----------------------------------------------------------
9 recursive calls
0 db block gets
73 consistent gets
0 physical reads
0 redo size
588 bytes sent via SQL*Net to client
469 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL>
僅此一項就可以看出為什麼ORACLE極力推薦使用CBO,從ORACLE 10g開始不支援RBO的緣故。所謂長江後浪推前浪,前浪死在沙灘上。
CBO知識點的總結
CBO優化器根據SQL語句生成一組可能被使用的執行計劃,估算出每個執行計劃的代價,並呼叫計劃生成器(Plan Generator)生成執行計劃,比較執行計劃的代價,最終選擇選擇一個代價最小的執行計劃。查詢優化器由查詢轉換器(Query Transform)、代價估算器(Estimator)和計劃生成器(Plan Generator)組成。
CBO優化器元件
CBO由以下元件構成:
· 查詢轉化器(Query Transformer)
查詢轉換器的作用就是等價改變查詢語句的形式,以便產生更好的執行計劃。它決定是否重寫使用者的查詢(包括檢視合併、謂詞推進、非巢狀子查詢/子查詢反巢狀、物化檢視重寫),以生成更好的查詢計劃。
The input to the query transformer is a parsed query, which is represented by a set of
query blocks. The query blocks are nested or interrelated to each other. The form of the
query determines how the query blocks are interrelated to each other. The main
objective of the query transformer is to determine if it is advantageous to change the
form of the query so that it enables generation of a better query plan. Several different
query transformation techniques are employed by the query transformer, including:
■ View Merging
■ Predicate Pushing
■ Subquery Unnesting
■ Query Rewrite with Materialized Views
Any combination of these transformations can be applied to a given query.
· 代價評估器(Estimator)
評估器通過複雜的演算法結合來統計資訊的三個值來評估各個執行計劃的總體成本:選擇性(Selectivity)、基數(Cardinality)、成本(Cost)
計劃生成器會考慮可能的訪問路徑(Access Path)、關聯方法和關聯順序,生成不同的執行計劃,讓查詢優化器從這些計劃中選擇出執行代價最小的一個計劃。
· 計劃生成器(Plan Generator)
計劃生成器就是生成大量的執行計劃,然後選擇其總體代價或總體成本最低的一個執行計劃。
由於不同的訪問路徑、連線方式和連線順序可以組合,雖然以不同的方式訪問和處理資料,但是可以產生同樣的結果
檢視ORACLE優化器
SQL> show parameter optimizer_mode;
NAME TYPE VALUE
--------------------------- ----------- -----------------
optimizer_mode string ALL_ROWS
修改ORACLE優化器
ORACLE 10g 優化器可以從系統級別、會話級別、語句級別三種方式修改優化器模式,非常方便靈活。
其中optimizer_mode可以選擇的值有: first_rows_n,all_rows. 其中first_rows_n又有first_rows_1000, first_rows_100, first_rows_10, first_rows_1
在Oracle 9i中,優化器模式可以選擇first_rows_n,all_rows, choose, rule 等模式:
Rule: 基於規則的方式。
Choolse:指的是當一個表或或索引有統計資訊,則走CBO的方式,如果表或索引沒統計資訊,表又不是特別的小,而且相應的列有索引時,那麼就走索引,走RBO的方式。
If OPTIMIZER_MODE=CHOOSE, if statistics do not exist, and if you do not add hints to SQL statements, then SQL statements use the RBO. You can use the RBO to access both relational data and object types. If OPTIMIZER_MODE=FIRST_ROWS, FIRST_ROWS_n, or ALL_ROWS and no statistics exist, then the CBO uses default statistics. Migrate existing applications to use the cost-based approach.
First Rows:它與Choose方式是類似的,所不同的是當一個表有統計資訊時,它將是以最快的方式返回查詢的最先的幾行,從總體上減少了響應時間。
All Rows: 10g中的預設值,也就是我們所說的Cost的方式,當一個表有統計資訊時,它將以最快的方式返回表的所有的行,從總體上提高查詢的吞吐
雖然Oracle 10g中不再支援RBO,Oracle 10g官方文件關於optimizer_mode引數的只有first_rows和all_rows.但是依然可以設定 optimizer_mode為rule或choose,估計是ORACLE為了過渡或向下相容考慮。如下所示。
系統級別
SQL> alter system set optimizer_mode=rule scope=both;
System altered.
SQL> show parameter optimizer_mode
NAME TYPE VALUE
-------------------------------- ----------- -----------------------
optimizer_mode string RULE
會話級別
會話級別修改優化器模式,只對當前會話有效,其它會話依然使用系統優化器模式。
SQL> alter session set optimizer_mode=first_rows_100;
Session altered.
語句級別
語句級別通過使用提示hints來實現。
SQL> select /*+ rule */ * from dba_objects where rownum <= 10;
作者:瀟湘隱者
出處:http://www.cnblogs.com/kerrycode/
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17172228/viewspace-2143875/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 簡單介紹Oracle的RBO/CBO優化器Oracle優化
- Oracle優化器(RBO與CBO)Oracle優化
- Oracle最佳化器(RBO與CBO)Oracle
- Oracle優化器的RBO和CBO方式Oracle優化
- Oracle的優化器的RBO和CBO方式Oracle優化
- 詳介oracle的RBO/CBO最佳化器 - 轉Oracle
- Oracle CBO 與 RBOOracle
- SQL優化器-RBO與CBO分別是什麼SQL優化
- CBO RBO簡介
- Oracle最佳化器RBO和CBO(轉載)Oracle
- 【效能優化】CBO,RBO在ORACLE中的應用優化Oracle
- Oracle Optimizer CBO RBOOracle
- Oracle的最佳化器的RBO和CBO方式Oracle
- 【效能優化】CBO,RBO在ORACLE 10g 中的應用優化Oracle 10g
- Oracle的優化器:RBO/CBO,RULE/CHOOSE/FIRST_ROWS/ALL_ROWS 名詞解釋Oracle優化
- Oracle Optimizer -RBO (理解Rule-based 優化器)Oracle優化
- CBO,RBO在ORACLE中的應用Oracle
- Oracle效能優化--Latch介紹Oracle優化
- Oracle效能優化---鎖介紹Oracle優化
- Oracle Optimizer -RBO (理解Rule-based 優化器)【Blog 搬家】Oracle優化
- Oracle SQL效能優化系列介紹OracleSQL優化
- 如何調優 Oracle SQL系列文章:查詢優化器介紹OracleSQL優化
- Oracle SQL優化總結OracleSQL優化
- Oracle SQL優化 總結OracleSQL優化
- 【sql調優】繫結變數與CBOSQL變數
- Oracle約束Constraint對於CBO優化器的作用OracleAI優化
- MySQL使用與優化總結MySql優化
- Oracle 優化引數 optimizer_mode 介紹Oracle優化
- 高併發&效能優化(一)------總體介紹優化
- 【效能優化】CBO優化器兩個內建的假設優化
- [總結] Oracle優化 – 分析統計Oracle優化
- oracle 學習總結(效能優化)Oracle優化
- 效能優化 - Oracle Tuning 總結 3 優化統計優化Oracle
- Oracle資料庫效能優化總結Oracle資料庫優化
- 效能優化 - Oracle Tuning 總結 1優化Oracle
- Go~介紹與優勢Go
- Oracle:RBOOracle
- Oracle學習系列—資料庫優化—RBO訪問路徑Oracle資料庫優化