RULE模式下是否FROM列表順序決定驅動表
前兩天在ITPUB看到這個問題,很多人有這個錯誤的概念,在RULE最佳化模式下,FROM語句中表的順序連線的驅動表,但是事實上並不是這麼簡單。
其實RULE最佳化模式已經基本上退出了歷史舞臺,不過既然有人提起了,就把概念描述清楚,對RULE最佳化模式不感興趣的可以無視這篇文章。
RULE方式是基於規則的,根據FROM列表中的順序判斷驅動表是規則之一,但是這個規則的優先順序並不高,如果有其他優先順序規則存在,則執行計劃會發生改變:
SQL> CREATE TABLE T1
2 (ID NUMBER,
3 NAME VARCHAR2(30));
Table created.
SQL> CREATE TABLE T2
2 (ID NUMBER,
3 NAME VARCHAR2(30));
Table created.
SQL> INSERT INTO T1
2 SELECT ROWNUM, TNAME
3 FROM TAB;
95 rows created.
SQL> INSERT INTO T2
2 SELECT ROWNUM, TABLE_NAME
3 FROM DBA_TABLES;
8923 rows created.
SQL> COMMIT;
Commit complete.
下面將最佳化模式改為RULE模式,看看是否驅動表的選擇與FROM列表中的位置有關:
SQL> ALTER SESSION SET OPTIMIZER_MODE = RULE;
Session altered.
SQL> SET AUTOT TRACE
SQL> SELECT *
2 FROM T1, T2
3 WHERE T1.ID = T2.ID;
95 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1792967693
------------------------------------
| Id | Operation | Name |
------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | MERGE JOIN | |
| 2 | SORT JOIN | |
| 3 | TABLE ACCESS FULL| T2 |
|* 4 | SORT JOIN | |
| 5 | TABLE ACCESS FULL| T1 |
------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."ID"="T2"."ID")
filter("T1"."ID"="T2"."ID")
Note
-----
- rule based optimizer used (consider using cbo)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
30 consistent gets
0 physical reads
0 redo size
4545 bytes sent via SQL*Net to client
558 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
95 rows processed
SQL> SELECT *
2 FROM T2, T1
3 WHERE T1.ID = T2.ID;
95 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 412793182
------------------------------------
| Id | Operation | Name |
------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | MERGE JOIN | |
| 2 | SORT JOIN | |
| 3 | TABLE ACCESS FULL| T1 |
|* 4 | SORT JOIN | |
| 5 | TABLE ACCESS FULL| T2 |
------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."ID"="T2"."ID")
filter("T1"."ID"="T2"."ID")
Note
-----
- rule based optimizer used (consider using cbo)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
30 consistent gets
0 physical reads
0 redo size
4545 bytes sent via SQL*Net to client
558 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
95 rows processed
可以看到,RULE最佳化器確實根據FROM列表中的位置來選擇驅動表,FROM列表中最後一個表被作為驅動表。
但是這只是沒有其他優先順序更高的規則存在下的情況,只要在表中建立索引,就會導致優先順序發生變化,從而導致上面的驅動表選擇發生變化:
SQL> CREATE INDEX IND_T1_ID ON T1(ID);
Index created.
SQL> SELECT *
2 FROM T2, T1
3 WHERE T1.ID = T2.ID;
95 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3280696534
-------------------------------------------------
| Id | Operation | Name |
-------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| T1 |
| 2 | NESTED LOOPS | |
| 3 | TABLE ACCESS FULL | T2 |
|* 4 | INDEX RANGE SCAN | IND_T1_ID |
-------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."ID"="T2"."ID")
Note
-----
- rule based optimizer used (consider using cbo)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
54 consistent gets
0 physical reads
0 redo size
4545 bytes sent via SQL*Net to client
558 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
95 rows processed
根據規則T1應該是驅動表,但是建立索引後,索引掃描的優先順序遠高於全表掃描,因此Oracle選擇T2作為驅動表,將T1的執行計劃變成了索引掃描。
T2上也存在索引,高優先順序的規則對於驅動表的選擇上條件等同,這時RULE最佳化器則又會根據FROM列表來判斷驅動表:
SQL> CREATE INDEX IND_T2_ID ON T2(ID);
Index created.
SQL> SELECT *
2 FROM T2, T1
3 WHERE T1.ID = T2.ID;
95 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3621112097
-------------------------------------------------
| Id | Operation | Name |
-------------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | TABLE ACCESS BY INDEX ROWID| T2 |
| 2 | NESTED LOOPS | |
| 3 | TABLE ACCESS FULL | T1 |
|* 4 | INDEX RANGE SCAN | IND_T2_ID |
-------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."ID"="T2"."ID")
Note
-----
- rule based optimizer used (consider using cbo)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
132 consistent gets
1 physical reads
0 redo size
4545 bytes sent via SQL*Net to client
558 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
95 rows processed
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-667851/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- windows驅動載入順序Windows
- 靜態順序表和動態順序表 對比
- 表的連線順序是否很重要
- linux驅動中使用順序鎖Linux
- 順序表
- 順序表應用5:有序順序表歸併
- 順序表應用6:有序順序表查詢
- 第2章 順序表及其順序儲存
- 列定義的順序和列儲存的順序
- 順序表的堆排序排序
- Java實現順序表Java
- 順序表的學習
- 順序表的實現
- ppt動畫出現順序怎麼設定 PPT設定動畫文字順序動畫
- Python中按字母順序對列表排序Python排序
- css3 列表按先後順序移動過來顯示CSSS3
- [RDMA] RDMA的不同操作是否保證順序?
- 順序表有序插入資料
- DS順序表--類實現
- 微信聊天表情順序設定方法 微信表情順序怎麼調?
- Linux核心驅動程式初始化順序的調整(轉)Linux
- 影像延遲載入 && 列表圖順序載入
- linux啟動順序Linux
- 資料結構 - 線性表 - 順序表資料結構
- java setPriority()設定優先順序Java
- C語言實現順序表C語言
- 演算法題———————輸入棧的入棧順序和出棧順序判斷是否合理演算法
- 程式設計模式-表驅動程式設計程式設計設計模式
- 順序表實現二分排序排序
- MySQL的驅動表與被驅動表MySql
- 考研資料結構-線性表-順序表資料結構
- 線性表-順序表C語言實現C語言
- 線性表的順序儲存-順序表,對“突然的自我”的否定,對自我的揚棄
- jQuery實現的新聞列表上下移動調整順序程式碼例項jQuery
- oracle pfile spfile啟動順序 優先順序 spfilesid 〉 spfile 〉 initsidOracle
- 基礎資料結構(一)---(最全)定長順序表的實現資料結構
- 教你定製Windows硬體驅動安裝目錄列表(轉)Windows
- 隨筆:MySQL 普通3表join順序MySql