2012-01-17 96 views
14

我有被構造爲隨後的Oracle查詢:Oracle是否使用短路評估?

SELECT * 
FROM  table 
WHERE X='true' OR 
     Y IN (complicated subquery) 

如果Oracle看到的是X不等於「真」將它仍然試圖評估WHERE子句的Y IN(子查詢)的一部分?而且,在這樣的陳述中,子查詢是否會針對表中的每個條目執行多次?我會喜歡的東西更好:

WITH subQ as (complicated subquery) 
SELECT * 
FROM  table 
WHERE X='true' OR 
     Y IN (SELECT id FROM subQ) 

回答

28

這取決於。 。 一般而言,Oracle不保證SQL語句將使用短路評估(儘管PL/SQL可保證執行短路評估)。 Oracle優化程序可以按照預期最有效的順序自由評估謂詞。這可能意味着首先評估第一個謂詞,並且只有匹配的行纔會評估第二個謂詞,但完全有可能發生相反的情況,或者Oracle將查詢轉換爲某種類型的UNION,並且在組合結果之前完全評估這兩個謂詞。也就是說,如果優化程序可以在編譯時確定謂詞將始終評估爲TRUEFALSE,那麼優化程序應該將其視爲一個常量。因此,例如,如果表上存在一個約束來防止X的值爲'true',那麼優化器根本不應該評估第二個謂詞(儘管不同版本的優化器將具有不同的檢測能力在編譯時某些東西是常量)。

至於你的問題的第二部分,沒有看到查詢計劃,很難說。如果有更有效的評估方法,Oracle優化器在將查詢從一種形式轉換爲另一種形式時往往會非常好。但是,通常情況下,如果subQ要返回相對較大數量的行(與table相比),則將查詢結構化爲EXISTS而不是IN會更有效。

+0

謝謝,這有助於很多。 – aoi222 2012-01-17 19:52:52

+0

「雖然PL/SQL保證執行短路評估」 你從哪裏拿? 我試過這個,並得到一個錯誤: 'declare var varchar2(30); begin 選擇'short circuit'into var from dual,其中1 = 0和1/0 = 0; end;' – 2012-02-08 17:25:33

+5

@IsaacKleinman - 這仍然是SQL。如果你把條件放在PL/SQL中,你會看到短路。如果(1 <2或1/0 = 1) 然後 dbms_output.put_line('Short circuit');則開始 ; end if; end;' – 2012-02-08 17:54:41

12

買者:甲骨文是不是我的主要專業領域。

基於成本的優化器應該知道X = 'true'的成本小於子查詢的成本,因此它可能會首先評估更簡單的備選方案。但是SQL中的AND和OR條件是而不是短路,如&&||是C及其派生詞。

子查詢可以是兩種形式之一:相關和非相關。

  • 一個相關子查詢必須被執行多次(這就是爲什麼他們是危險的性能),因爲相關性是指子查詢的結果取決於在該行「目前正在評估」)的一些方式。
  • 一個不相關的子查詢只會執行一次。

實施例相關的子查詢:

SELECT * 
    FROM Table1 
WHERE X = 'true' 
    OR Y IN (SELECT Z FROM Table2 WHERE Table2.A = Table1.B) 

實施例不相關的子查詢:

SELECT * 
    FROM Table1 
WHERE X = 'true' 
    OR Y IN (SELECT Z FROM Table2 WHERE Table2.A > 13) 
+1

這也非常有幫助,謝謝。 – aoi222 2012-01-17 19:54:54

1

無論什麼樣的優化可能會或可能不會與ANDOR做,如果因爲任何原因,你必須強制評估的特定順序,你可以重寫查詢,使用其中短路評估保證等工具。

例如:

select * from table 1 
where case when X = 'true' then 1 
      when Y in (select ....) then 1 
     end = 1 

如果X是「真」,則情況下表達式計算爲1,第二個「何時」被跳過並且條件評估爲TRUE。如果X不是「真」,那麼評估IN條件。