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

Oracle WHERE 條件順序真的影響性能嗎?實驗證明:右到左解析但無性能差異

     編輯:Oracle 資料庫基礎

爭論焦點

關於 WHERE 子句條件順序是否影響性能,歷來有三種觀點:

  1. RBO 模式下無影響(10g 默認 RBO?實為 10g 默認 ALL_ROWS CBO)。
  2. CBO 下「最選擇性條件放最右」——因 SQL 從右到左執行。
  3. CBO 下「最選擇性條件放最左」——實測性能更好。

官方文檔從 8i 到 11g 均無明確說明條件順序影響性能。本文通過三組實驗給出結論。

實驗一:語法解析順序 —— 從右到左

-- 9i / 10g / 11g 均一致
SELECT 'ok' FROM dual WHERE 1/0 = 1 AND 1 = 2;  -- 不報錯(右側 1=2 先判為 FALSE,短路)
SELECT 'ok' FROM dual WHERE 1 = 2 AND 1/0 = 1;  -- ORA-01476: divisor is equal to zero
-- 證明:解析器按從右到左順序評估條件表達式

實驗二:9i 運行時過濾順序 —— 從右到左

DROP TABLE temp;
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:數字轉換在右
SELECT * FROM temp WHERE TO_NUMBER(t2) > 1 AND t1 = 'sz';  -- 成功(先過濾 t1='sz',再轉換 t2)

-- 條件順序 2:數字轉換在左
SELECT * FROM temp WHERE t1 = 'sz' AND TO_NUMBER(t2) > 1;  -- ORA-01722: invalid number
-- 9i 確認:運行時也按從右到左過濾,導致 'abcde' 被 TO_NUMBER 報錯

10g 行為變化:兩條語句均不報錯,優化器自動調整過濾順序(將 t1='sz' 先應用),體現 CBO 智能重排。

實驗三:10g/11g 運行時順序驗證 —— 仍從右到左

構建帶副作用的函數觀察調用順序:

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
-- 證明:10g/11g 運行時過濾仍遵循從右到左順序

核心結論

維度結論
語法解析從右到左(短路求值)
9i 運行時過濾從右到左(隱式轉換報錯可證)
10g/11g+ 運行時過濾從右到左(函數調用順序可證)
CBO 執行計劃生成與條件書寫順序無關,基於統計信息自動選擇最優訪問路徑
性能影響無實質性能差異,優化器會重排謂詞順序

最佳實踐建議

  1. 可讀性優先:按業務邏輯順序書寫(如主鍵優先、關聯鍵優先)。
  2. 避免隱式轉換:WHERE TO_NUMBER(col) > 1 寫法極危險,應修正數據模型或使用函數索引。
  3. 複雜邏輯用括號明確分組:WHERE (A=1 AND B=2) OR (C=3)。
  4. 依賴統計信息:定期 DBMS_STATS.GATHER_TABLE_STATS,讓 CBO 自動決策。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved