2009-09-18 45 views
6

tengo esta cláusula en una combinación en un procedimiento almacenado que heredé:T-SQL ISNULL() Optimización

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

¿Cómo voy a volver a escribir esto para eliminar el ISNULL, ya que está causando graves problemas de rendimiento?

+0

SQL Server? – AnthonyWJones

Respuesta

7

en este caso, me gustaría tener una sentencia if, comprobando @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 

pero no estoy tan seguro de que sea mucho más rápido.

+0

Si hay un índice es. – recursive

+0

Un índice no es una preocupación, incluso si existiera uno, el índice solo se usaría en la segunda mitad. Es mucho mejor que las sugerencias de ISNULL/COALESCE. –

1

@due_date_limit es una variable de procedimiento almacenado para que pueda tenerse en cuenta a partir de esta consulta todos juntos:

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) 

puede ayudar

+0

Esto manejará las cosas con gracia, pero es un desperdicio realizar 1 = 1 equivalente. –

2

hay un índice en DUE_DATE? Si no, agrega uno y luego verifica el rendimiento. Si ya existe, a continuación, cambiar a dos estados separados

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

Pero se da cuenta de que no filtrado (cuando @due_date_limit es nulo), o el filtrado utilizando un < = potencialmente puede devolver un número considerable de registros que eliminará cualquier oportunidad para usar un índice y requerirá un escaneo completo de la tabla. Esto puede ser lo que estás experimentando.

3

La causa más común de bajo rendimiento con este tipo de consulta es que el optimizador no puede estar seguro de cuál será el valor típico de @due_date_limit para la mayoría de las consultas. A menudo, el plan generado y reutilizado por ejecuciones posteriores favorece el caso en el que el valor es nulo.

A partir de SQL 2005 puede guiar el optimizador de utilizar el "Optimizar para" opción: -

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

Si el parámetro es nulo, ¿por qué aún desea comparar los valores? No lo hace, entonces no use ISNULL/COALESCE para parámetros opcionales. –

0

Desde @due_date_limit es una variable de procedimiento almacenado, sólo puede comprobar que NULL antes de la consulta y configurarlo a un valor predeterminado si es necesario, eliminando así la verificación ISNULL en la cláusula WHERE.

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

y luego su cláusula WHERE simplemente tener este aspecto: Versión

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

La respuesta de astander es una mejor solución si necesita que sea igual al registro de columna para cumplir con la condición del operador '<='; de lo contrario, establezca si antes de la consulta, ya que será más rápido y no habrá ningún control. – johntrepreneur