Forza SQL Server per eseguire le condizioni della query come scritto?


14

Sto usando SQL Server 2008 R2 e ho questa pseudo query (SP):

select ...
from ...
WHERE    @LinkMode IS NULL
     AND (myColumn IN (...very long-running query...))
     ...
     ...

Il problema è che l'esecuzione della query richiede molto tempo, anche se eseguo l'SP con @LinkMode=2.

Come hai notato, la query di lunga durata dovrebbe essere eseguita solo se @LinkMode è null, il che non è il caso qui. Nel mio caso @LinkMode = 2!

Tuttavia, se lo cambio in:

 select ...
    from ...
    WHERE    1=2
         AND (myColumn IN (...very long time exeted query...))
     ...
     ...

la SP non correre veloce.

Ho già sentito che a volte l'ottimizzatore può ottimizzare l'ordine dei criteri.

Quindi chiedo:

  • Anche se l'ottimizzatore sceglie un percorso diverso, cosa può essere più veloce del controllo se =null? Voglio dire, penso che il controllo if a==nullsia molto più veloce rispetto all'esecuzione dell'altra query lunga ...

  • Come posso forzare SQL Server per eseguire la query come l'ho scritta (lo stesso ordine)?

Risposte:


22

Stai cadendo nella trappola " Catch-All Query ", che è spiegato molto bene da Gail Shaw qui .

Per riassumere il problema: SQL Server ottimizza l'overhead significativo della compilazione di query memorizzando nella cache un piano di query dopo la compilazione e successivamente controllando la cache per un piano di query corrispondente prima di una successiva compilazione. La "corrispondenza" che si verifica qui è puramente testuale, quindi il valore effettivo di una variabile non influirà su questo.

È buono il 99% delle volte, ma in alcuni casi è negativo . Un caso in cui è negativo è quando qualcuno tenta di costruire una clausola WHERE come se fosse come un'istruzione IF in cortocircuito in C, ecc. Questo non funziona bene, perché il compilatore SQL deve creare un piano di query che funzionerà indipendentemente di quali siano effettivamente i valori dei parametri e l'unico modo in cui è in grado di gestire queste "intelligenti" condizioni logiche di commutazione nella clausola WHERE è creare un semplice piano di forza bruta che scansiona l'intera tabella, filtrando le righe mentre procede , senza sfruttare alcun indice.

Non a caso, ciò li rende uniformemente lenti, indipendentemente dai valori dei parametri / variabili.


8

Non esiste un modo garantito per forzare il server SQL ad eseguire le condizioni della clausola in una sequenza specifica. L'ottimizzatore li valuterà sempre nell'ordine che ritiene opportuno.

Quello che puoi fare è qualcosa del genere:

IF @LinkMode IS NULL
BEGIN
    select ...
    from ...
    WHERE (myColumn IN (...very long time exeted query...))
         ...
         ...
END
ELSE
BEGIN
    select ...
    from ...
    WHERE ...
         ...
END

3

Se è un'opzione, utilizzare un'istruzione IF per eseguire la forma appropriata della query. Inoltre, in SQL, dici al motore db cosa fare, non come farlo - le cose non vengono eseguite dall'inizio alla fine. Può essere difficile prevedere cosa farà esattamente. Probabilmente lo sai però;)


2

Probabilmente anche SQL dinamico funzionerebbe, poiché in quel caso lo Strumento per ottimizzare le query dovrebbe ottenere i valori effettivi in ​​fase di esecuzione (correggimi se sbaglio, in realtà non sono sicuro, ma sembra ricordare di averlo usato per situazioni simili) . Ma sono con gli altri in questo, in quanto una clausola IF / ELSE ti servirebbe meglio, poiché è la soluzione più semplice e facile che farà esattamente ciò che è necessario.

Per riferimento futuro nel caso in cui non l'abbia ancora usato, un sito orribile brutto con un esempio funzionante per SQL dinamico può essere trovato qui per esempio: http://sqlusa.com/bestpractices/dynamicsql/


1

Consiglierei il costrutto IF / ELSE .. Se per qualsiasi motivo che non funziona per te, puoi sempre considerare di usare l'opzione WITH RECOMPILE ..


Potresti forse approfondire come potrebbe essere il "costrutto if / else"? : D
jcolebrand

Stavo per suggerire di usare OPTION (WITH RECOMPILE), in quanto ciò genererebbe ogni volta un piano ideale: il ritardo di compilazione aggiungerebbe spese generali, ma sospetto che in questo caso sia meglio nel complesso.
SqlRyan,
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.