RBO 解析 `FROM` 子句遵循從右到左順序,最後寫入的表 (Driving Table) 最先被處理。策略:選擇列數最少的表作為 Driving Table。
-- TAB1 16,384 列,TAB2 1 列
SELECT COUNT(*) FROM TAB1, TAB2; -- 0.96 秒 (TAB2 為 Driving Table,佳)
SELECT COUNT(*) FROM TAB2, TAB1; -- 26.09 秒 (TAB1 為 Driving Table,差)
三表以上連接:選擇交叉表 (被其他表引用的表) 作為 Driving Table。
範例:`EMP` 連接 `LOCATION`、`CATEGORY`,`EMP` 為交叉表,應置於 `FROM` 最後。
Oracle 自下而上解析 WHERE 條件。原則:
-- 低效:先評估高選擇性條件,再做子查詢
SELECT ... FROM EMP E
WHERE SAL > 50000
AND JOB = 'MANAGER'
AND 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO); -- 156.3 秒
-- 高效:先評估相關子查詢 (最耗資源),最後簡單過濾
SELECT ... FROM EMP E
WHERE 25 < (SELECT COUNT(*) FROM EMP WHERE MGR=E.EMPNO)
AND SAL > 50000
AND JOB = 'MANAGER'; -- 10.6 秒
注意:CBO 會自動重排序條件評估順序,此規則主要針對 RBO 或輔助 CBO 穩定計畫。
每次 SQL 執行伴隨 Parse、Bind、Execute、Fetch 多次往返。合併請求可大幅降低開銷。
-- 方法 1:兩次往返 (最差)
SELECT EMP_NAME, SALARY, GRADE FROM EMP WHERE EMP_NO = 342;
SELECT EMP_NAME, SALARY, GRADE FROM EMP WHERE EMP_NO = 291;
-- 方法 2:PL/SQL 迴圈游標,仍多次 Execute/Fetch (次差)
DECLARE CURSOR C1 (E_NO NUMBER) IS SELECT ... FROM EMP WHERE EMP_NO = E_NO;
BEGIN OPEN C1(342); FETCH ...; OPEN C1(291); FETCH ...; END;
-- 方法 3:單一 SQL 自連接 (最佳)
SELECT A.EMP_NAME, A.SALARY, A.GRADE,
B.EMP_NAME, B.SALARY, B.GRADE
FROM EMP A, EMP B
WHERE A.EMP_NO = 342 AND B.EMP_NO = 291;
掌握 RBO 連接順序、WHERE 條件排序邏輯、拒絕 `SELECT *`、合併多次查詢為單一 SQL 並調大 `ARRAYSIZE`,是應用層面最直接、投資報酬率最高的調優手法。下一章將探討 `EXISTS` vs `IN`、子查詢轉連接、臨時表應用等進階重寫技巧。