關於 WHERE 條件撰寫順序是否影響效能,流傳兩種說法:
官方文件 (8i~11g) 從未明確說明順序影響效能。本文透過四個實驗徹底釐清。
-- 1. 不報錯 (先算 1=2 為 FALSE,短路不執行 1/0)
SELECT 'ok' FROM dual WHERE 1/0 = 1 AND 1 = 2;
-- 2. 報錯 ORA-01476: divisor is equal to zero (先算 1/0)
SELECT 'ok' FROM dual WHERE 1 = 2 AND 1/0 = 1;
結論:解析階段確從右向左評估條件。
CREATE TABLE temp (t1 VARCHAR2(10), t2 VARCHAR2(10));
INSERT INTO temp VALUES ('zm','abcde');
INSERT INTO temp VALUES ('sz','1');
INSERT INTO temp VALUES ('sz','2');
COMMIT;
-- 1. 9i 不報錯 (先過濾 t1='sz' 再轉數字)
-- 2. 9i 報錯「無效數字」 (先轉數字 abcde 失敗)
SELECT * FROM temp WHERE TO_NUMBER(t2) > 1 AND t1='sz';
SELECT * FROM temp WHERE t1='sz' AND TO_NUMBER(t2) > 1;
10g 兩條皆不報錯,說明執行引擎已具備條件重排與短路優化能力。
CREATE OR REPLACE FUNCTION f1(v_in VARCHAR2) RETURN VARCHAR2 IS BEGIN DBMS_OUTPUT.PUT_LINE('exec F1'); RETURN v_in; END;
CREATE OR REPLACE FUNCTION f2(v_in VARCHAR2) RETURN VARCHAR2 IS BEGIN DBMS_OUTPUT.PUT_LINE('exec F2'); RETURN v_in; END;
SET SERVEROUTPUT ON;
SELECT 1 FROM dual WHERE f1('1')='1' AND f2('1')='1'; -- 輸出: exec F2 → exec F1
SELECT 1 FROM dual WHERE f2('1')='1' AND f1('1')='1'; -- 輸出: exec F1 → exec F2
函數呼叫順序證明 10g 運行時仍遵循從右向左評估。
表 診療項目目錄:
操作類型='1' → 3,251 筆類別='Z' → 170 筆PL/SQL 迴圈各執行 1,000 次:
| 順序 | 耗時 (秒) | 順序 | 耗時 (秒) |
|---|---|---|---|
| 操作類型='1' 在右 | 0.093 / 1.06 / 0.998 | 類別='Z' 在右 | 1.014 / 0.999 / 1.014 |
時間差異在統計誤差範圍內,無顯著差別。
RBO 模式下,FROM 子句中表順序 (由大到小、驅動表在右) 決定 Nested Loops 外層迴圈次數,直接影響效能。CBO 會自動根據統計資訊決定最佳連接順序。切記:條件順序無關痛癢,表順序才是大事 (RBO 時代)。