首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

SQL WHERE 條件順序真的影響 Oracle 效能嗎?完整實驗證明毫無影響

     編輯:Oracle 資料庫基礎

爭論背景

關於 WHERE 條件撰寫順序是否影響效能,流傳兩種說法:

  1. 最具選擇性 (過濾率最高) 的條件放最右邊,因 SQL 從右向左執行。
  2. 最具選擇性的條件放最左邊,效能更好。

官方文件 (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;

結論:解析階段確從右向左評估條件。

實驗二:9i 執行順序從右向左,10g 已優化

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 兩條皆不報錯,說明執行引擎已具備條件重排與短路優化能力。

實驗三:10g 確認執行順序仍從右向左 (用 PL/SQL 函數追蹤)

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 筆
  • 兩條件 AND → 1 筆

PL/SQL 迴圈各執行 1,000 次:

順序耗時 (秒)順序耗時 (秒)
操作類型='1' 在右0.093 / 1.06 / 0.998類別='Z' 在右1.014 / 0.999 / 1.014

時間差異在統計誤差範圍內,無顯著差別。

原理深度解析

  1. 全表掃描場景: 兩種順序執行計畫相同 (全表掃描),Oracle 依序讀取每個資料塊,對塊內每一行同時檢查所有條件 (向量化評估),不存在「先過濾 170 筆再過濾 3,251 筆」的中間結果集產生。
  2. 有索引/連接場景: 優化器優先利用索引或連接條件縮減結果集 (Access Predicates),再對縮減後的行套用其餘 Filter Predicates。此時條件順序更無影響。

特別補充:表連接順序才真正關鍵

RBO 模式下,FROM 子句中表順序 (由大到小、驅動表在右) 決定 Nested Loops 外層迴圈次數,直接影響效能。CBO 會自動根據統計資訊決定最佳連接順序。切記:條件順序無關痛癢,表順序才是大事 (RBO 時代)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved