Operatori logici OR AND in condizioni e ordine delle condizioni in WHERE


33

Esaminiamo queste due affermazioni:

IF (CONDITION 1) OR (CONDITION 2)
...

IF (CONDITION 3) AND (CONDITION 4)
...

Se lo CONDITION 1è TRUE, lo faràCONDITION 2 controllato?
Se lo CONDITION 3è FALSE, verrà CONDITION 4controllato?

Che dire delle condizioni WHERE: il motore di SQL Server ottimizza tutte le condizioni in aWHERE clausola? I programmatori dovrebbero collocare le condizioni nel giusto ordine per essere sicuri che l'ottimizzatore di SQL Server lo risolva nel modo giusto ?

AGGIUNTO:

Grazie a Jack per il collegamento, sorpresa dal codice t-sql:

IF  1/0 = 1 OR 1 = 1
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result


IF  1/0 = 1 AND 1 = 0
      SELECT 'True' AS result
ELSE
      SELECT 'False' AS result

Non c'è rilancio a questo caso genera un'eccezione Dividi per zero .

CONCLUSIONE:

Se C ++ / C # / VB presenta un corto circuito, perché SQL Server non può averlo?

Per rispondere veramente a questo, diamo un'occhiata a come entrambi funzionano con le condizioni. C ++ / C # / VB hanno tutti un corto circuito definito nelle specifiche della lingua per accelerare l'esecuzione del codice. Perché preoccuparsi di valutare le condizioni N OR quando la prima è già vera o le condizioni M AND quando la prima è già falsa.

Come sviluppatori, dobbiamo essere consapevoli del fatto che SQL Server funziona in modo diverso. È un sistema basato sui costi. Per ottenere il piano di esecuzione ottimale per la nostra query, il processore di query deve valutare ogni condizione in cui e assegnargli un costo. Questi costi vengono quindi valutati nel loro insieme per formare una soglia che deve essere inferiore alla soglia definita che SQL Server ha per un buon piano. Se il costo è inferiore alla soglia definita, viene utilizzato il piano, in caso contrario l'intero processo viene ripetuto nuovamente con una diversa combinazione di costi di condizione. Il costo qui è una scansione o una ricerca o un join unione o un hash join ecc ... Per questo motivo il corto circuito come è disponibile in C ++ / C # / VB semplicemente non è possibile. Potresti pensare che forzare l'uso dell'indice su una colonna sia considerato un corto circuito, ma non è così. Impone solo l'uso di quell'indice e con ciò accorcia l'elenco dei possibili piani di esecuzione. Il sistema è ancora basato sui costi.

Come sviluppatore devi essere consapevole che SQL Server non esegue i cortocircuiti come avviene in altri linguaggi di programmazione e non c'è niente che puoi fare per forzarlo.


Da dove proviene il blocco preventivo finale? Potresti aggiungere un riferimento?
Nick Chammas,

Risposte:


25

Non esiste alcuna garanzia in SQL Server se o in quale ordine le istruzioni verranno elaborate in una WHEREclausola. La singola espressione che consente il cortocircuito delle istruzioni è CASE- WHEN. Quanto segue proviene da una risposta che ho pubblicato su Stackoverflow:

In che modo SQL Server cortocircuita la valutazione delle condizioni

Lo fa quando ne ha voglia, ma non nel modo in cui pensi immediatamente.

Come sviluppatore devi essere consapevole che SQL Server non esegue i cortocircuiti come avviene in altri linguaggi di programmazione e non c'è niente che puoi fare per forzarlo .

Per ulteriori dettagli, controlla il primo link nel precedente post sul blog, che sta conducendo a un altro blog:

Cortocircuito di SQL Server?

Il verdetto finale? Bene, non ne ho ancora uno, ma è probabilmente sicuro affermare che l'unica volta in cui è possibile garantire un cortocircuito specifico è quando si esprimono più condizioni QUANDO in un'espressione CASE. Con le espressioni booleane standard, l'ottimizzatore sposta le cose come meglio crede in base alle tabelle, agli indici e ai dati di cui stai eseguendo la query.


2
Apparentemente ci sono alcuni casi limite (o un bug) in cui persino case non è sicuro
Jack Douglas

1
Dimostro anche un altro caso (ah!) In cui si CASErompe: dba.stackexchange.com/questions/12941/…
Aaron Bertrand


0

SQL è un linguaggio di programmazione dichiarativo . Diversamente, diciamo, C ++ che è un linguaggio di programmazione imperativo .

Vale a dire che puoi dire quello che vuoi nel risultato finale, ma non puoi dettare come il risultato viene eseguito, dipende tutto dal motore.

L'unico vero modo per garantire il "cortocircuito" (o qualsiasi altro flusso di controllo ) all'interno WHEREconsiste nell'utilizzare viste indicizzate, tabelle temporanee e meccanismi simili.

PS. Puoi anche usare i suggerimenti del piano di esecuzione (per "suggerire" al motore come eseguire una query, quali indici usare e COME usarli), ho pensato che avrei dovuto menzionarlo, mentre siamo su questo argomento ...


-4

1) - OPPURE (una o entrambe le condizioni saranno VERE)

se la condizione 1 è TRUE, verrà verificata anche la condizione 2 che può essere TRUE o FALSE

--AND (entrambe le condizioni devono essere VERE)

se la condizione 1 è FALSE, la condizione 2 non verrà controllata


"se la condizione 1 è FALSE, la condizione 2 non verrà controllata" Questo non è vero. Vedi la risposta sopra . SQL Server può ancora valutare la condizione 2 perché non esegue la valutazione di corto circuito nelle WHEREclausole.
Nick Chammas,

-4

L'unico modo per controllare come le condizioni all'interno della clausola WHERE è utilizzare le parentesi per raggrupparle.

WHERE Col1 = 'Something' AND Col2 = 'Something' OR Col3 = 'Something' and Col4 = 'Something'

è molto diverso da

WHERE (Col1 = 'Something' AND Col2 = 'Something') OR (Col3 = 'Something' and Col4 = 'Something')

Solo curioso. In che modo queste due condizioni sono diverse? Diversi risultati, prestazioni, piano di esecuzione? Ho pensato che sarebbero stati equivalenti.
ypercubeᵀᴹ

Con il primo devi abbinare Col1, Col4 e Col2 o Col3. Nella seconda riga per abbinare Col1 e Col2 o devi abbinare Col3 e Col4 ma Col1 e Col4 non dovranno mai essere valutati entrambi insieme.
mrdenny,

1
No, hai torto. ANDha una precedenza maggiore di OR. Entrambi sono equivalenti. Quello che dici sarebbe vero per la WHERE Col1 = x AND (Col2 = x OR Col3 = x) AND Col4 = xquery. Vedi test SQL-Fiddle
ypercubeᵀᴹ
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.