1. 程式人生 > >基於RULE的優化器(學習筆記)

基於RULE的優化器(學習筆記)

崔華《基於Oracle的sql優化》學習筆記

1.1 基於RULE的優化器

(1) CBO

(2)RBO

和CBO相比,RBO是有其明顯許可權的。在使用RBO的情況下,執行計劃一旦出了問題,很難對其做調整。另外,如果使用了RBO則目標SQL的寫法,甚至是目標SQL中所涉及的各個物件在該SQL文字中出現的先後順序都可能影響RBO執行計劃的選擇我,更糟糕的是,Oracle資料庫中很好的特性、功能不能再RBO中使用因為他們不能被RBO鎖支援。

只要出現如下情形之一,那麼即便修改了優化器模式或者使用了RULE Hnint,Oracle依然不會使用RBO(而是強制使用CBO)。

(1)  目標SQL中設計的對此昂有IOT(indexOrganized Table)。

(2)  目標SQL中設計的物件有分割槽表。

(3)  使用了平行查詢或者並行DML。

(4)  使用了星形連線

(5)  使用了hash連線

(6)  使用了索引快速全掃描

(7)  使用了函式索引

(8)  …...

這種情況下我們是很難對RBO選擇的執行計劃做調整的,其中一個十分關鍵的原因是不能使用hint。因為如果在目標SQL中使用了Hint,就意味著自動啟動了CBO,即Oracle會以CBO來解析Hint的目標SQL。這裡僅有兩個例外,就是RULE Hint和SRIVING_SITE Hint,他可以在RBO下使用並且不自動啟用CBO。

那麼是不是在使用RBO的情況下就沒有辦法對執行計劃進行調整了呢??

當然不是這樣,只是這種情況下我們的調整手段非常有限。其中的一種可行的方法就是等價改寫目標SQL,比如在目標SQL的where條件中對NUMBER或者DATE型別的列上加上0(如果是varchar2或者char型別,可以加上一個空字元,例如||’’),這樣就可以讓原本可以走的索引現在走不了。對於包含多表連線的目標sql而言,這種改變甚至可以影響表連線的順序,進而就可以實現在使用RBO的情況下對該目標SQL的執行計劃作出調整的目的。

但是如果出現了兩條或者兩條以上的等級值相同的執行路徑的情況,那麼RBO此時該如何選擇呢?很簡單,此時RBO會依據目標SQL中所涉及的相關物件在資料字典快取(Data Dictionary cache)中的快取順序和目標SQL中所涉及的各個物件在目標SQL文字中出現的先後順序來綜合判斷。這也就意味著我們還可以通過調整相關物件在資料字典中的快取順序,改變目標SQL中所涉及的各個物件在該SQL文字中出現的先後順序來調整其執行計劃。

實驗:使用RBO的情況下,對目標SQL的執行計劃調整。

create table emp_temp as select * from  emp;
 
create index idx_mgr_temp on emp_temp(mgr);
 
create index idx_deptno_temp on emp_temp(deptno);
 
 
select * from emp_temp where  mgr>100 and deptno>100;

###在當前session中配置優化器模式為RULE

alter session set optimizer_mode='RULE';

SET AUTOT TRACE EXP

假如我們發現走索引IDX_DEPTNO_TEMP不如走索引IDX_MGR_TEMP的執行效率高,或者我們想讓RBO走索引IDX__MGR_TEMP,那麼我們該如何讓做??

可以加一個0不讓它走索引:

Select * from  emp_temp where mgr>100 anddeptno+0>100;
 
08:28:11 [email protected] SQL>Select * from  emp_temp where mgr>100 anddeptno+0>100;
 
no rows selected
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2973289657
 
----------------------------------------------------
| Id  |Operation                   | Name         |
----------------------------------------------------
|   0 |SELECT STATEMENT            |              |
|*  1 |  TABLE ACCESS BY INDEX ROWID| EMP_TEMP     |
|*  2 |   INDEX RANGE SCAN          | IDX_MGR_TEMP |
----------------------------------------------------
 
Predicate Information (identified by operationid):
---------------------------------------------------
 
   1 -filter("DEPTNO"+0>100)
   2 -access("MGR">100)
 
Note
-----
   - rulebased optimizer used (consider using cbo)
 
 
Statistics
----------------------------------------------------------
         1  recursive calls
         0  db block gets
         2  consistent gets
         0  physical reads
         0  redo size
       799  bytes sent via SQL*Net toclient
       512  bytes received via SQL*Netfrom client
         1  SQL*Net roundtrips to/fromclient
         0  sorts (memory)
         0  sorts (disk)
         0  rows processed
 
09:58:53 [email protected] SQL>
 

我們可以看到已經改變了執行計劃。

剛才我先建立索引IDX_MGR_TEMP,再建立索引IDX_DEPTNO_TEMP,所以IDX_MGR_TEMP先快取,在快取IDX_DEPTNO_TEMP這種情形下RBO選擇的是走對索引IDX_DEPTNO_TEMP的索引範圍掃,如果反過來呢??

先刪除索引IDDX_MGR_TEMP

09:58:53 [email protected] SQL>DROP INDEXIDX_MGR_TEMP;
 
Index dropped.
再建立該索引:
 
10:15:20 [email protected] SQL>create indexidx_mgr_temp on emp_temp(mgr);
 
Index created.
 
 
10:16:05 [email protected] SQL>Select * from  emp_temp where mgr>100 and deptno>100;
 
no rows selected
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2973289657
 
----------------------------------------------------
| Id  |Operation                   | Name         |
----------------------------------------------------
|   0 |SELECT STATEMENT            |              |
|*  1 |  TABLE ACCESS BY INDEX ROWID| EMP_TEMP     |
|*<span style="color:#FF0000;">  2 |   INDEX RANGE SCAN          | IDX_MGR_TEMP |</span>
----------------------------------------------------
 
Predicate Information (identified by operationid):
---------------------------------------------------
 
   1 -filter("DEPTNO">100)
   2 -access("MGR">100)
 
Note
-----
   - rulebased optimizer used (consider using cbo)
 
 
Statistics
----------------------------------------------------------
         3  recursive calls
         0  db block gets
         6  consistent gets
         0  physical reads
          0 redo size
       799  bytes sent via SQL*Net toclient
       512  bytes received via SQL*Netfrom client
         1  SQL*Net roundtrips to/fromclient
         0  sorts (memory)
         0  sorts (disk)
         0  rows processed
 
10:17:48 [email protected] SQL>

如上實驗可知,當目標SQL有兩條或者兩條以上的執行路徑的登記相同時,我們確實可以通過調整相關物件在資料字典快取中的快取順序來影響RBO對於執行計劃的選擇。

Create table emp_temp1 as select * from emp;
 
10:25:30 [email protected] SQL>Selectt1.mgr,t2.deptno from emp_temp t1,emp_temp1 t2
10:26:27  2  Where t1.empno=t2.empno;
 
14 rows selected.
 
Execution Plan
----------------------------------------------------------
Plan hash value: 1323777565
 
-----------------------------------------
| Id  |Operation           | Name      |
-----------------------------------------
|   0 |SELECT STATEMENT    |           |
|   1 |  MERGE JOIN         |           |
|   2 |   SORT JOIN         |           |
|   3 |    TABLE ACCESS FULL| EMP_TEMP1 |
|*  4 |   SORT JOIN         |           |
|   5 |    TABLE ACCESS FULL| EMP_TEMP  |
-----------------------------------------
 
Predicate Information (identified by operationid):
---------------------------------------------------
 
   4 -access("T1"."EMPNO"="T2"."EMPNO")
      filter("T1"."EMPNO"="T2"."EMPNO")
 
Note
-----
   - rulebased optimizer used (consider using cbo)
 
 
Statistics
----------------------------------------------------------
         1  recursive calls
         0  db block gets
         6  consistent gets
         4  physical reads
         0  redo size
       778  bytes sent via SQL*Net toclient
       524  bytes received via SQL*Netfrom client
         2  SQL*Net roundtrips to/fromclient
         2  sorts (memory)
         0  sorts (disk)
        14  rows processed
 
10:31:02 [email protected] SQL>

我們發現emp_tem1p作為驅動表,

注意:排序合併連線,從嚴格意義上來講,並沒有驅動表和被驅動表的概念,這裡只是為了方便闡述而人為的給排序合併連線添加了概念。

那麼改變該SQL的SQL文字中的位置會怎麼樣呢??

 
Select t1.mgr,t2.deptno from emp_temp1  t2,emp_temp  t1
 Where t1.empno=t2.empno;
 
10:31:02 [email protected] SQL>Selectt1.mgr,t2.deptno from emp_temp1 t2,emp_temp  t1
10:36:15  2   Where t1.empno=t2.empno;
 
      MGR     DEPTNO
---------- ----------
     7902         20
     7698         30
     7698         30
     7839         20
     7698         30
     7839         30
     7839         10
     7566         20
                   10
     7698         30
     7788         20
     7698         30
     7566         20
     7782         10
 
14 rows selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 2135683657
 
-----------------------------------------
| Id  |Operation           | Name      |
-----------------------------------------
|   0 |SELECT STATEMENT    |           |
|   1 |  MERGE JOIN         |           |
|   2 |  SORT JOIN         |           |
|   3 |   TABLE ACCESS FULL| EMP_TEMP  |
|*  4 |  SORT JOIN         |           |
|   5 |   TABLE ACCESS FULL| EMP_TEMP1 |
-----------------------------------------
 
Predicate Information (identified by operationid):
---------------------------------------------------
 
   4 -access("T1"."EMPNO"="T2"."EMPNO")
      filter("T1"."EMPNO"="T2"."EMPNO")
 
Note
-----
   - rulebased optimizer used (consider using cbo)
 
 
Statistics
----------------------------------------------------------
         1  recursive calls
          0 db block gets
         6  consistent gets
         0  physical reads
         0  redo size
       778  bytes sent via SQL*Net toclient
       524  bytes received via SQL*Netfrom client
         2  SQL*Net roundtrips to/fromclient
          2 sorts (memory)
         0  sorts (disk)
        14  rows processed
 
10:36:15 [email protected] SQL>

我們發現,驅動表變為emp_temp了。

說明,當目標SQL有兩條或者兩條以上的執行路徑的等級值相同時,我們確定可以通過改變目標SQL中所涉及的各個物件在該SQL文字中出現的先後順序來影響RBO對其執行計劃的選擇。

注意:以上幾個實驗都是就RBO模式。RBO不支援HASH join

Emp有主鍵,emp_temp上empno列沒有索引。

10:43:50 [email protected] SQL>Select t1.mgr,t2.deptno from emp  t1,emp_temp t2
10:44:00   2   Where t1.empno=t2.empno;

14 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 367190759

-------------------------------------------------
| Id  | Operation                    | Name     |
-------------------------------------------------
|   0 | SELECT STATEMENT             |          |
|   1 |  NESTED LOOPS                |          |
|   2 |   NESTED LOOPS               |          |
|   3 |    TABLE ACCESS FULL         | EMP_TEMP |
|*  4 |    INDEX UNIQUE SCAN         | PK_EMP   |
|   5 |   TABLE ACCESS BY INDEX ROWID| EMP      |
-------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - access("T1"."EMPNO"="T2"."EMPNO")

Note
-----
   - rule based optimizer used (consider using cbo)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         22  consistent gets
          0  physical reads
          0  redo size
        778  bytes sent via SQL*Net to client
        524  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         14  rows processed

10:44:00 [email protected] SQL>

修改該SQL文字的表順序:

Select t1.mgr,t2.deptno from emp_temp t2,emp  t1
 Where t1.empno=t2.empno;
 
10:44:00 [email protected] SQL>Selectt1.mgr,t2.deptno from emp_temp t2, emp t1
10:49:57  2    Where t1.empno=t2.empno;
 
14 rows selected.
 
 
Execution Plan
----------------------------------------------------------
Plan hash value: 367190759
 
-------------------------------------------------
| Id  |Operation                    | Name     |
-------------------------------------------------
|   0 |SELECT STATEMENT             |          |
|   1 |  NESTED LOOPS                |          |
|   2 |   NESTED LOOPS               |         |
|   3 |   TABLE ACCESS FULL         |EMP_TEMP |
|*  4 |    INDEX UNIQUE SCAN         | PK_EMP   |
|   5 |   TABLE ACCESS BY INDEX ROWID| EMP      |
-------------------------------------------------
 
Predicate Information (identified by operationid):
---------------------------------------------------
 
   4 -access("T1"."EMPNO"="T2"."EMPNO")
 
Note
-----
   - rulebased optimizer used (consider using cbo)
 
 
Statistics
----------------------------------------------------------
         1  recursive calls
         0  db block gets
        22  consistent gets
         0  physical reads
         0  redo size
       778  bytes sent via SQL*Net toclient
       524  bytes received via SQL*Netfrom client
         2  SQL*Net roundtrips to/fromclient
         0  sorts (memory)
         0  sorts (disk)
        14  rows processed
 
10:49:57 [email protected] SQL>

可以看出執行計劃走的是巢狀迴圈,且驅動表依然是表EMP_TEMP,這就證明:如果RBO僅憑目標SQL各條執行路徑等級值的大小就可以選擇出執行計劃。那麼無論怎麼調整相關物件在該SQL的SQL文字中的位置,對於該SQL最終的執行計劃都不會有任何影響。

相關推薦

基於RULE優化學習筆記

崔華《基於Oracle的sql優化》學習筆記 1.1 基於RULE的優化器 (1) CBO (2)RBO 和CBO相比,RBO是有其明顯許可權的。在使用RBO的情況下,執行計劃一旦出了問題,很難對其做調整。另外,如果使用了RBO則目標SQL的寫法,甚至是目標SQL

Spring攔截學習筆記

SpringMVC 中的Interceptor 攔截請求是通過HandlerInterceptor 來實現的 在SpringMVC 中定義一個Interceptor 非常簡單,主要有兩種方式 第一種方式是: 要定義的Interceptor類要實現了Spr

tensorflow視訊記憶體、載入模型、優化個人筆記

在使用tensorflow做實驗的這短暫一段時間內,遇到了不少問題,把還沒忘問題寫在這裡,方便以後查閱。 1. 執行sess=tf.Session() 或 sess=tf.InteractiveSession()後發現所有GPU的視訊記憶體全部佔滿 A:

2.3 如何得到真實的執行計劃 《基於Oracle的優化學習筆記

  if( hash_values.count > 0 ) then     for i in hash_values.first .. hash_values.last loop            dbms_output.put_line('----------------------------

2.5 Oracle裡常見執行計劃 《基於Oracle的優化學習筆記

與表訪問相關的執行計劃 全表掃描的關鍵字是:TABLE ACESS FULL ROWID掃描的關鍵字:TABLE ACESS BY USER ROWID 或 TABLE ACESS BY INDEX ROWID 與B樹相關的執行計劃 索引唯一掃描:INDEX UN

5.2 Oracle裡收集與檢視統計資訊的方法 《基於Oracle的優化學習筆記

收集統計資訊有兩種方法:一是通過analyze命令,一是通過dbms_stats包 使用analyze收集統計資訊的方法 刪除索引的統計資訊 analyze index index_name delete statistics; 以估算的模式,取樣的比例15%

5.6全域性統計資訊《基於Oracle的優化學習筆記

Oracle裡面的全域性統計資訊(global statistics)是直接衝物件本身這一級收集統計資訊,而不是從下一級物件“推導”或“彙總”出來的統計資訊。 當適用DBMS_STATS包的儲存過程收集統計資訊時,引數granularity用於指定全域性統計資訊的收集策

6.4常見的Hint《基於Oracle的優化學習筆記

與優化器相關的Hint /*+ ALL_ROWS */ 它的含義是啟用CBO /*+ FIRST_ROWS(n) */ 優化器啟用CBO,而且依據返回頭n條的記錄的響應時間來決定SQL的執行計劃。 注意,first_rows(n)與first_rows_n並

基於Keras的LSTM多變數時間序列預測 學習筆記

本文翻譯自Jason Brownlee的部落格https://machinelearningmastery.com/multivariate-time-series-forecasting-lstms-keras/ 本部落格主要參考以下中文版部落格 https://blog.csdn.net/qq_280

UI框架—基於UGUI學習筆記

UI框架—基於UGUI 一、需求分析 (一)、需求分析UML圖 1、通過UIManger來自作解析json檔案。 2、UML各種關係 二、知識點 (一)、原理知識 1、單例模式 定義一個靜態的物件 在外界訪問 在內部構造。 構造方法私

學習筆記51微控制器的中斷功能及其相關的暫存

51微控制器中斷系統          引起CPU中斷的根源,稱為中斷源,中斷源向CPU提出中斷請求,CPU暫時中斷原來的事務A,轉去處理事件B,對時間B處理完畢後,再回來原來的地方(斷點),稱為中斷返回。實現上述中斷功能的部件稱為中斷系統(中斷機構)。 中斷優先順序決定了

基於appium自動化測試案例12--使用yaml 進行資料配置學習筆記

在編寫appium自動化測試指令碼中,經常需要配置裝置及app的引數,如:desired_caps={} #裝置平臺名稱 desired_caps['platformName']='Android' #裝置名稱 desired_caps['deviceName']='127.

基於appium自動化測試案例7--螢幕截圖學習筆記

#coding=utf-8 #匯入之前登陸判斷方法 from find_element.kyb_login import driver driver.find_element_by_id('com.tal.kaoyan:id/login_email_edittext').c

fireflyLogin網絡工具設計模式——類工廠學習筆記

nbsp dict var class requests result ini 業務層 指向 一、RequestKeyID(業務id) 二、FireflyRequestHelper(對外提供初始化接口,提供網絡回調代理方法,供FireflySafeLoginHelper使用

網頁排版中的浮動和定位學習筆記

mage hidden alt images blog clear ul li -a www CSS中的浮動和定位 在了解CSS中的浮動和定位之前有必要先了解清楚標準流和脫離標準流的特性 雖然浮動和定位很重要,但是在以後的網頁寫作中,還是盡量少用,最好別亂用,不然後

數字和表達式學習筆記

解釋器 結果 2.0 1.0 解決 imp 整數 oat 小數 1、交互式Python解釋器可以當做非常強大的計算器使用,試試以下的例子:   >>> 2 + 2   4   或者   >>> 53762 + 235253   28892

java中的try-catch-finnal異常處理學習筆記

不堪 java sha highlight 抽取 最終 throwable 關鍵字 學習筆記 一、異常概述 異常:Exception,是在運行發生的不正常情況。 原始異常處理: if(條件) {   處理辦法1  處理辦法2  處理辦法3} if(條件) {   處理辦法

深入研究Spark SQL的Catalyst優化原創翻譯

超越 href 語法 英文 更多 com edi 此外 並行化 Spark SQL是Spark最新和技術最為復雜的組件之一。它支持SQL查詢和新的DataFrame API。Spark SQL的核心是Catalyst優化器,它以一種新穎的方式利用高級編程語言特性(例如Sca

1. PostgreSQL-安裝和基本配置學習筆記

安裝和配置 日常使用 buffer java、 note 安裝完成 for ora har 1 PostgreSQL簡介1.1 概述??PostgreSQL數據庫是目前功能最強大的開源數據庫,支持豐富的數據類型(如JSON和JSONB類型,數組類型)和自定義類型。而且它提供

一、作用域是什麽 學習筆記—— 《你不知道的JavaScript》

筆記 變量 如何 都是 先來 png 模擬 特定 function 因為全部都是文字不太好理解,所以盡可能地把所有的文字都畫成了圖,便於理解。 作用域是什麽 傳統編譯流程: JavaScript 引擎會在語法分析和代碼生成階段,通過特定的步驟,對運行性能進行優化