驅動表普遍認為是由SQL語句的寫法決定的,簡單的說,就是FROM語句后面的表列表中的最后一個。由於SQL語句是從后向前進行分析,Oracle會根據FROM語句從后到前將各個表依次連接起來。
SQL> CREATE TABLE T1 AS SELECT * FROM USER_TABLES; 表已創建。 SQL> CREATE TABLE T2 AS SELECT * FROM USER_INDEXES; 表已創建。 SQL> SET AUTOT ON EXP SQL> SELECT COUNT(*) FROM T1, T2 2 WHERE T1.TABLE_NAME = T2.TABLE_NAME; COUNT(*) ---------- 37 Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE 1 0 SORT (AGGREGATE) 2 1 MERGE JOIN 3 2 SORT (JOIN) 4 3 TABLE ACCESS (FULL) OF 'T2' 5 2 SORT (JOIN) 6 5 TABLE ACCESS (FULL) OF 'T1' SQL> SELECT COUNT(*) FROM T2, T1 2 WHERE T1.TABLE_NAME = T2.TABLE_NAME; COUNT(*) ---------- 37 Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE 1 0 SORT (AGGREGATE) 2 1 MERGE JOIN 3 2 SORT (JOIN) 4 3 TABLE ACCESS (FULL) OF 'T1' 5 2 SORT (JOIN) 6 5 TABLE ACCESS (FULL) OF 'T2'
根據這個例子,可以看出,SQL語句的寫法對於驅動表的影響。
然而,實際上驅動表和連接順序的選擇要比上面的觀點復雜的多,下面對稍微調整一下這個例子。
SQL> ALTER TABLE T1 ADD CONSTRAINT PK_T1 PRIMARY KEY (TABLE_NAME); 表已更改。 SQL> SELECT COUNT(*) FROM T1, T2 2 WHERE T1.TABLE_NAME = T2.TABLE_NAME; COUNT(*) ---------- 37 Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE 1 0 SORT (AGGREGATE) 2 1 NESTED LOOPS 3 2 TABLE ACCESS (FULL) OF 'T2' 4 2 INDEX (UNIQUE SCAN) OF 'PK_T1' (UNIQUE) SQL> SELECT COUNT(*) FROM T2, T1 2 WHERE T1.TABLE_NAME = T2.TABLE_NAME; COUNT(*) ---------- 37 Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE 1 0 SORT (AGGREGATE) 2 1 NESTED LOOPS 3 2 TABLE ACCESS (FULL) OF 'T2' 4 2 INDEX (UNIQUE SCAN) OF 'PK_T1' (UNIQUE)
僅僅是給T1增加了一個主鍵,就發現不管SQL語句怎么寫驅動表都是T2。
即使是RBO,確定表連接順序的規則也是比較復雜的:
1.優化器產生一系列連接順序,每次均把不同的表作為驅動表。而且,優化器根據下面的算法產生每個連接順序。
為了確定連接順序中各個表的位置,優化器根據RBO執行計划的排名,在剩余的表中找到表訪問路徑排名最高的表,然后不斷的重復這個過程,依次確定連接順序中每個表的前后順序。
對於連接順序中的每張表,優化器根據執行計划的排名選擇一種連接方式將當前表和前面的表或數據源連接在一起。
2.優化器在執行計划的結果集中進行選擇。優化器的目標是最大程度的選擇內部表采用索引掃描方式的NESTED LOOPS連接操作。
通常情況下,優化器在選擇執行計划時,不會考慮表在FROM語句中出現的順序。優化器依次根據下面的規則來作出選擇
優化器選擇執行計划使得內部表為全表掃描的NESTED LOOPS連接盡可能的少;
如果采用上面的條件出現了平局的情況,則優化器選擇盡可能少出現SORT MERGE操作的執行計划;
如果仍然出現平局的情況,則優化器將選擇表訪問路徑中排名最高的表作為驅動表;
如果這時仍然是平局,則優化器會把FROM語句中最后出現的表最為驅動表。
摘自:http://blog.csdn.net/sinat_19628145/article/details/50938665