2009-09-18 19 views
6

ho questa clausola su un join in una stored procedure che ho ereditato:T-SQL ISNULL) Optimization (

WHERE a.is_active = 1 
AND b.due_date <= ISNULL(@due_date_limit, b.due_date) 

Come dovrei ri-scrivere questo per rimuovere l'ISNULL come sta causando gravi problemi di prestazioni?

+0

SQL Server? – AnthonyWJones

risposta

7

in questo caso, avrei un'istruzione if, controllando @due_date_limit

IF (@due_date_limit IS NULL) 
BEGIN 
    ... 
    WHERE a.is_active = 1 --not required to compare b.due_date <= b.due_date 
END 
ELSE 
BEGIN 
    ... 
    WHERE a.is_active = 1 
    AND  b.due_date <= @due_date_limit 
END 
2
AND @due_date_limit IS NULL OR b.due_date <= @due_date_limit 

ma non sono così sicuro che sarebbe molto più veloce.

+0

Se c'è un indice lo è. – recursive

+0

Un indice non è un problema: anche se ne esisteva uno, l'indice sarebbe utilizzato solo nel 2 ° semestre. È molto meglio dei suggerimenti ISNULL/COALESCE. –

1

@due_date_limit è una variabile stored procedure in modo che possa essere fattorizzato da questa query tutti insieme:

if (@due_date_limit is NULL) 
    <run query that works when @due_date_limit is NULL> 
else 
    <run query that works when @due_date_limit is NOT NULL> 
1
COALESCE(@due_date_limit, b.due_date) 

può aiutare

+0

Questo gestirà le cose con grazia, ma è uno spreco eseguire un equivalente 1 = 1. –

2

c'è un indice su due_Date? In caso contrario, aggiungere uno e quindi controllare le prestazioni. Se v'è già, poi cambiare per due prospetti separati

If @due_date_limit is null 
    Select [stuff] 
    From Table 
    Else 
    Select [stuff] 
    From Table 
    Where b.due_date <= @due_date_limit 

Ma si rende conto che non filtrando (quando @due_date_limit è nullo), o il filtro utilizzando un < = potenzialmente in grado di restituire un numero consistente di record che eliminerà qualsiasi opportunità utilizzare un indice e richiederà una scansione completa della tabella. Questo potrebbe essere ciò che stai vivendo.

3

La causa più comune di prestazioni scadenti con questo tipo di query è perché l'ottimizzatore non può essere sicuro del valore tipico di @due_date_limit per la maggior parte delle query. Spesso il piano generato e riutilizzato dalle esecuzioni successive favorisce il caso in cui il valore è nullo.

Come di SQL 2005 è possibile guidare l'ottimizzatore utilizzando il "Ottimizza per" l'opzione: -

WHERE a.is_active = 1 
AND b.due_date <= ISNULL(@due_date_limit, b.due_date) 
OPTION (OPTIMIZE FOR (@due_date_limit = '09/01/2009')) 
+0

Se il parametro è nullo, perché vorresti comunque confrontare i valori? Non lo fai, quindi non utilizzare ISNULL/COALESCE per i parametri opzionali. –

0

Dal @due_date_limit è una variabile stored procedure, si può solo controllare la presenza di NULL prima che la query e impostarlo ad un valore predefinito, se necessario, eliminando così il controllo ISNULL nella clausola WHERE.

IF (@due_date_limit IS NULL) 
BEGIN 
    SET @due_date_limit = '09/01/2009'; 
END 

e poi il tuo clausola WHERE sarebbe semplicemente simile a questa: versione

WHERE a.is_active = 1 
AND b.due_date <= @due_date_limit 
+0

la risposta di astander è una soluzione migliore se è necessario che sia uguale al record della colonna per soddisfare la condizione dell'operatore <= ', altrimenti impostare se prima della query in questo modo poiché sarà più veloce e non ci sarà alcun controllo. – johntrepreneur