INSERTE la diferencia de rendimiento entre las tablas temporales y la variable de tabla

12

Tengo el siguiente problema en SQL Server 2005: intentar insertar algunas filas en una variable de tabla lleva mucho tiempo en comparación con la misma inserción que usa una tabla temporal.

Este es el código para insertar en la variable de tabla

DECLARE @Data TABLE(...)
INSERT INTO @DATA( ... )
SELECT ..
FROM ...

Este es el código para insertar en la tabla temporal

CREATE #Data TABLE(...)
INSERT INTO #DATA( ... )
SELECT ..
FROM ...
DROP TABLE #Data

La tabla temporal no tiene claves ni índices, la parte de selección es la misma entre las 2 consultas y el número de resultados devueltos por la selección es de ~ 10000 filas. El tiempo necesario para ejecutar la selección solo es de ~ 10 segundos.

La versión de la tabla temporal tarda hasta 10 segundos en ejecutarse, tuve que detener la versión variable de la tabla después de 5 minutos.

Tengo que usar una variable de tabla porque la consulta es parte de una función de valor de tabla, que no permite el acceso a la tabla temporal.

Plan de ejecución para la versión de tabla variable Plan de ejecución

Plan de ejecución para la versión de la tabla temporal Plan de ejecución

munissor
fuente

Respuestas:

8

La diferencia obvia entre los dos planes es que el rápido es paralelo y el más lento en serie.

Esta es una de las limitaciones de los planes que se insertan en las variables de la tabla. Como se menciona en los comentarios (y parece que tuvo el efecto deseado), podría intentar hacer

INSERT INTO @DATA ( ... ) 
EXEC('SELECT .. FROM ...')

para ver si eso supera la limitación.

Martin Smith
fuente
Fue una gran sugerencia, aunque pensé que no se podía usar EXECen una función ... supongo que estaba equivocado
Lamak
1
@Lamak - Doh! No puede, así que esto no funcionará para el OP. Invalid use of a side-effecting operator 'INSERT EXEC' within a function.. El OPENQUERYtrabajo alrededor de trabajo podría sin embargo.
Martin Smith
Ah, es bueno saberlo, gracias por la aclaración
Lamak
2
Como regla general, no desea utilizar variables de tabla si va a esperar que se devuelva un gran conjunto de datos. Las tablas temporales suelen ser más rápidas en este caso.
HLGEM
1
@munissor, entonces no use una función con valores de tabla. Si desea un mejor consejo, publique exactamente lo que está haciendo.
HLGEM
-1

Las variables de tabla a veces son más lentas porque no hay estadísticas sobre las variables de tabla y, por lo tanto, el optimizador siempre asume solo un registro.

Sin embargo, no puedo garantizar que este sea el caso aquí, tendrá que echar un vistazo a la información de "filas estimadas" en el plan de consulta para la variable de tabla.

Yoel Halb
fuente
¿Cómo afectaría eso una inserción en una variable de tabla?
Martin Smith
Eso es lo que parece estar sucediendo, ya que puede ver que no solo hay una diferencia entre uniones paralelas y seriales, sino también entre uniones de bucle hash y anidadas, aparentemente el optimizador asume que, dado que la variable de tabla tiene un registro en mente, el resultado de la consulta también será un registro, una vez más, la única forma de demostrarlo sería ver las estadísticas reales de cada parte de la consulta, pero el hecho es que todas las consultas que involucran variables de tabla terminan con uniones de bucle y procesamiento en serie, así que creo que es justo sospecharlo aquí
yoel halb