5

Ho una query che deve essere dinamica su alcune colonne, ovvero ottengo un parametro e in base al suo valore decido quale colonna recuperare nella mia clausola Where . Ho implementato questa richiesta utilizzando l'espressione "caso":L'utilizzo di "CASE" nella clausola Where per scegliere varie colonne danneggia le prestazioni

(CASE @isArrivalTime WHEN 1 THEN ArrivalTime ELSE PickedupTime END) 
>= DATEADD(mi, [email protected], @sTime) 
AND (CASE @isArrivalTime WHEN 1 THEN ArrivalTime ELSE PickedupTime END) 
< DATEADD(mi, [email protected], @fTime) 

Se @isArrivalTime = 1 poi scelto ArrivalTime colonna altro ha scelto PickedupTime colonna. Ho un indice cluster su ArrivalTime e indice non cluster su PickedupTime.

Ho notato che quando utilizzo questa query (con @isArrivalTime = 1), la mia prestazione è molto peggiore rispetto al solo utilizzo di ArrivalTime.

Forse il Query Optimizer non può usare \ scegliere l'indice correttamente in questo modo?

Ho confrontato i piani di esecuzione e ho notato che quando sto usando il CASE il 32% del tempo viene sprecato nella scansione dell'indice, ma quando non ho usato il CASE (just used ArrivalTime`) solo il 3% è stato sprecato su questo indice di scansione.

Qualcuno sa il motivo di questo?

risposta

0

tenta di impostare confine datetime:

declare @resSTime datetime 
     ,@resFTime datetime 

set @resSTime = DATEADD(mi, [email protected], @sTime) 
set @resFTime = DATEADD(mi, [email protected], @fTime) 

e cercare di cambiare a caso 'o'

(ArrivalTime >= @resSTime 
    and ArrivalTime < @resFTime 
    and @isArrivalTime = 1) 
or (PickedupTime >= @resSTime 
    and PickedupTime < @resFTime 
    and @isArrivalTime <> 1) 
+0

Yap, che ha risolto il mio problema. Grazie! –

2

La differenza tra il 2 è probabilmente dovuta al diverso numero di righe che deve eseguire la scansione. Poiché la tua query è probabile, il risultato finale di un join tra più tabelle. Tieni presente che una scansione è ... beh, come dice il nome, una scansione di tutte le righe. È possibile controllare il piano per il numero stimato di righe per farsi un'idea.

Se si utilizza un filtro su un campo dinamico (utilizzando caso per esempio), un indice su tale campo non può essere utilizzato dal motore. In un caso come questo, è meglio usare SQL dinamico per produrre il giusto sql di cui hai bisogno e usare exec_sql. O usare se le affermazioni per interrogare direttamente la cosa giusta.

È possibile trovare questo utile per l'utilizzo di SQL dinamico, spiegherà perché e come.

http://www.sommarskog.se/dynamic_sql.html

Problemi correlati