2012-01-17 13 views
14

Ho una query di Oracle che è strutturata come segue:Oracle utilizza la valutazione di cortocircuito?

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

Se Oracle vede che X è uguale a 'vero' sarà ancora cercare di valutare la (subquery) parte Y IN della clausola WHERE? Inoltre, in una dichiarazione come questa, la sottoquery dovrebbe essere eseguita più volte per ogni voce nella tabella? Sarei meglio con qualcosa di simile:

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

risposta

28

Dipende. . In generale, Oracle non garantisce che un'istruzione SQL utilizzi la valutazione di cortocircuito (sebbene sia garantito che PL/SQL esegua la valutazione di cortocircuito). L'ottimizzatore Oracle è libero di valutare i predicati in qualsiasi ordine si aspetti che sia più efficiente. Ciò potrebbe significare che il primo predicato viene valutato per primo e solo le righe corrispondenti hanno valutato il secondo predicato ma è del tutto possibile che avvenga il contrario o che Oracle trasformi la query in una sorta di UNION e valuti completamente entrambi i predicati prima di combinare i risultati .

Detto questo, se l'ottimizzatore può determinare in fase di compilazione che un predicato valuterà sempre a TRUE o FALSE, l'ottimizzatore dovrebbe considerarlo come una costante. Quindi, se, ad esempio, esiste un vincolo sulla tabella che impedisce a X di avere un valore di 'true', l'ottimizzatore non dovrebbe valutare il secondo predicato (sebbene versioni diverse dell'ottimizzatore abbiano abilità diverse da rilevare che qualcosa è una costante al momento della compilazione).

Per quanto riguarda la seconda parte della domanda, senza visualizzare i piani di query, è molto difficile dirlo. L'ottimizzatore di Oracle tende ad essere abbastanza bravo a trasformare query da una forma all'altra se esistono modi più efficienti di valutarla. In generale, tuttavia, se subQ restituirà un numero relativamente elevato di righe rispetto a table, potrebbe essere più efficiente strutturare la query come EXISTS anziché come IN.

+0

Grazie, questo aiuta molto. – aoi222

+0

"anche se PL/SQL è garantito per eseguire la valutazione di cortocircuito" da dove lo si prende? Ho provato questo e ho ricevuto un errore: 'declare var varchar2 (30); selezionare 'cortocircuito' in var da duale dove 1 = 0 e 1/0 = 0; fine; ' –

+5

@IsaacKleinman - Questo è ancora SQL. Se metti le condizioni in PL/SQL, vedrai un cortocircuito. 'begin if (1 <2 or 1/0 = 1) then dbms_output.put_line ('Cortocircuito'); fine se; fine; ' –

12

Caveat: Oracle non è la mia principale area di competenza.

L'ottimizzatore basato sul costo dovrebbe sapere che il costo di X = 'true' è inferiore alla subquery, quindi è probabile che prima valuti l'alternativa più semplice. Ma le condizioni AND e OR in SQL sono non in cortocircuito come && e || in C e derivati.

La sottoquery può essere una delle due forme: correlata e non correlata.

  • A correlato sub-query deve essere eseguito tante volte (è per questo che sono pericolosi per performance) perché la correlazione significa che il risultato sub-query dipende in qualche modo sulla riga 'in corso di valutazione').
  • Una sottoquery non correlata verrà eseguita una sola volta.

Esempio correlato sub-query:

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

esempio non correlato sub-query:

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

Anche questo è stato molto utile, grazie. – aoi222

1

Indipendentemente da ciò che l'ottimizzatore può o non può fare con AND e OR, se per qualsiasi motivo è necessario rispettare un ordine specifico di valutazione, è possibile riscrivere la query, utilizzando altri strumenti in cui è garantita la valutazione di corto circuito.

Ad esempio:

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

Se X è 'vero' allora l'espressione caso restituisce 1, la seconda "quando" viene saltato e la condizione restituisce TRUE. Se X non è "vero", viene valutata la condizione IN.

Problemi correlati