2011-05-18 19 views
5

Tengo un procedimiento almacenado que tarda menos de un segundo en ejecutarse normalmente. Los usuarios querían datos de otra tabla en esa consulta, así que fusioné esos datos con UNION ALL y un grupo de columnas ficticias que faltaban en la nueva tabla.SQL 2000 UNION TODAS ruinas consulta optimización

Funcionó bien en las pruebas, pero cuando lo implementamos en un servidor SQL 2000, comenzó a obtener tiempos de espera. La consulta anterior se ejecuta en menos de un segundo y las dos consultas nuevas se ejecutan en menos de un segundo, pero cuando se combinan utilizando UNION ALL, la consulta expira.

Esta es una idea general de cómo se ve la consulta. La consulta real tiene unos 20 parámetros de entrada y devuelve unos 30 o 40 columnas, pero esto debe darle la idea básica:

CREATE PROCEDURE dbo.SearchHistory 
(
    @Criteria1 bigint, 
    @Criteria2 int, 
    @Criteria3 varchar(10) 
) 
AS 
BEGIN 
    -- Part 1 
    SELECT 
     A, 
     NULL AS B, 
     0 AS C, 
     D 
    FROM TableA 
    WHERE @Criteria1 IS NULL 
    AND @Criteria3 IS NULL 
    AND (A = @Criteria2 OR @Criteria2 IS NULL) 

UNION ALL 

    -- Part 2 
    SELECT 
     A, 
     NULL AS B, 
     0 AS C, 
     E 
    FROM TableA 
    WHERE @Criteria1 IS NULL 
    AND @Criteria3 IS NULL 
    AND (A = @Criteria2 OR @Criteria2 IS NULL) 

UNION ALL 

    -- Part 3 
    SELECT 
     A, 
     B, 
     C, 
     D 
    FROM TableB 
    WHERE (F = @Criteria1 OR @Criteria1 IS NULL) 
    AND (A = @Criteria2 OR @Criteria2 IS NULL) 
    AND (G = @Criteria3 OR @Criteria3 IS NULL) 
END 

En el ejemplo anterior, @ Criteria1 no es nulo, por lo que la parte 1 y 2 devolverá 0 filas, y la parte 3 solo devuelve 3 filas. Pero si comento la Parte 1 y 2, termina inmediatamente; si los dejo en, obtengo un tiempo muerto.

¿Cómo convence a SQL Server para que no se meta con su plan de ejecución en una situación como esta?

+0

¿Qué plan de ejecución le ofrece con 'UNION ALL'? Además, ¿qué sucede si simplemente inserta en una '@ table_variable' en 3 instrucciones separadas y selecciona de eso al final? –

+0

(Creo que hay un error de sintaxis de una coma requerida que falta en la lista de selección; ¿es este el código real?) –

+0

¿Cambia el procedimiento a 'CREAR PROCEDIMIENTO dbo.SearchHistory WITH RECOMPILE (...' help? –

Respuesta

3

Creo que su problema se debe a la detección de parámetros de SQL Server.

http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/

http://blogs.msdn.com/b/queryoptteam/archive/2006/03/31/565991.aspx

me he encontrado con él unas cuantas veces. Hay algunas formas de evitarlo. P.ej. use WITH RECOMPILE como lo sugirió @Biff MaGriff. La manera más fácil de solucionarlo es convertir todos los parámetros de entrada en parámetros locales y usar los locales.

+0

WITH RECOMPILE ha agotado todas las consultas, no solo donde @ Criteria1 no es NULL. No he tenido tiempo para probando las variables locales todavía, demasiadas cosas pasando, pero todavía intento probarlo. –

0

Esto no se puede responder sin ver los planes de ejecución (publicarlos como imágenes, una para cada parte y otra para la consulta de unión). Una solución alternativa es utilizar una tabla temporal en la que inserte las partes por separado. Sin embargo, una mejor solución sería solucionar la consulta en primer lugar.

Cuestiones relacionadas