Estoy aprendiendo más detalles en la variable de tabla. Dice que las tablas temporales siempre están en el disco y las variables de tabla están en la memoria, es decir, el rendimiento de la variable de tabla es mejor que la tabla temporal porque la variable de tabla usa menos operaciones de E / S que la tabla temporal.
Pero a veces, si hay demasiados registros en una variable de tabla que no pueden estar contenidos en la memoria, la variable de tabla se colocará en el disco como la tabla temporal.
Pero no sé cuáles son los "demasiados registros". 100.000 registros? o 1000,000 registros? ¿Cómo puedo saber si una variable de tabla que estoy usando está en la memoria o en el disco? ¿Hay alguna función o herramienta en SQL Server 2005 para medir la escala de la variable de la tabla o avisarme cuando la variable de la tabla se coloca en el disco desde la memoria?
tempDB
, que "en memoria" es un mito. Además: el optimizador de consultas siempre considerará que las variables de tabla contienen exactamente una fila; si tiene mucho más, esto puede conducir a planes de ejecución realmente malos.tempdb
(pero también puede estar completamente en la memoria)Respuestas:
Su pregunta muestra que ha sucumbido a algunos de los conceptos erróneos comunes que rodean las variables de tabla y las tablas temporales.
He escrito una respuesta bastante extensa en el sitio de DBA mirando las diferencias entre los dos tipos de objetos. Esto también responde a su pregunta sobre el disco frente a la memoria (no vi ninguna diferencia significativa en el comportamiento entre los dos).
Con respecto a la pregunta en el título sobre cuándo usar una variable de tabla frente a una tabla temporal local, no siempre tiene una opción. En las funciones, por ejemplo, solo es posible usar una variable de tabla y si necesita escribir en la tabla en un ámbito secundario, solo una
#temp
tabla lo hará (los parámetros con valores de tabla permiten acceso de solo lectura ).Si tiene una opción, algunas sugerencias están a continuación (aunque el método más confiable es simplemente probar ambas con su carga de trabajo específica).
Si necesita un índice que no se puede crear en una variable de tabla, entonces, por supuesto, necesitará una
#temporary
tabla. Sin embargo, los detalles de esto dependen de la versión. Para SQL Server 2012 y posteriores, los únicos índices que se podían crear en las variables de la tabla eran aquellos creados implícitamente mediante una restricciónUNIQUE
oPRIMARY KEY
. SQL Server 2014 introdujo la sintaxis de índice en línea para un subconjunto de las opciones disponibles enCREATE INDEX
. Esto se ha extendido desde entonces para permitir condiciones de índice filtrado.INCLUDE
Sin embargo, todavía no es posible crear índices con columnas -d o índices de almacén de columnas en las variables de tabla.Si va a agregar y eliminar repetidamente un gran número de filas de la tabla, use una
#temporary
tabla. Eso es compatibleTRUNCATE
(que es más eficiente queDELETE
para tablas grandes) y, además, las inserciones posteriores que siguen aTRUNCATE
pueden tener un mejor rendimiento que las que siguen aDELETE
como se ilustra aquí .#temporary
tabla. Es compatible con la creación de estadísticas que permite que el plan se vuelva a compilar dinámicamente de acuerdo con los datos (aunque para las tablas temporales en caché en los procedimientos almacenados, el comportamiento de la compilación debe entenderse por separado).SELECT
declaración potencialmente costosa , entonces considere que usar una variable de tabla bloqueará la posibilidad de que esto use un plan paralelo.#temp
tabla dentro de un usuario, los bloqueos de transacciones pueden mantenerse más tiempo que para las variables de la tabla (potencialmente hasta el final de la transacción frente al final de la declaración dependiendo del tipo de bloqueo y nivel de aislamiento) y también puede evitar el truncamiento deltempdb
registro de transacciones hasta que la transacción del usuario finaliza. Entonces esto podría favorecer el uso de variables de tabla.#temporary
tablas. Bob Ward señala en sutempdb
presentación que esto puede causar contención adicional en las tablas del sistema en condiciones de alta concurrencia. Además, cuando se trata con pequeñas cantidades de datos, esto puede marcar una diferencia apreciable en el rendimiento .Efectos del intercambio de conjuntos de filas
fuente
id
y usoOPTION (RECOMPILE)
probablemente estaría bien para eso, pero pruebe ambos.Use una variable de tabla si es para una cantidad muy pequeña de datos (miles de bytes)
Use una tabla temporal para muchos datos
Otra forma de pensarlo: si cree que podría beneficiarse de un índice, estadísticas automatizadas o cualquier bondad del optimizador de SQL, entonces su conjunto de datos es probablemente demasiado grande para una variable de tabla.
En mi ejemplo, solo quería poner unas 20 filas en un formato y modificarlas como un grupo, antes de usarlas para ACTUALIZAR / INSERTAR una tabla permanente. Entonces, una variable de tabla es perfecta.
Pero también estoy ejecutando SQL para rellenar miles de filas a la vez, y definitivamente puedo decir que las tablas temporales funcionan mucho mejor que las variables de tabla.
Esto no es diferente a cómo los CTE son una preocupación por una razón de tamaño similar: si los datos en el CTE son muy pequeños, encuentro que un CTE funciona tan bien o mejor que lo que ofrece el optimizador, pero si es bastante grande, entonces te duele mucho
Mi comprensión se basa principalmente en http://www.developerfusion.com/article/84397/table-variables-v-temporary-tables-in-sql-server/ , que tiene muchos más detalles.
fuente
Microsoft dice aquí
fuente
Estoy totalmente de acuerdo con Abacus (lo siento, no tengo suficientes puntos para comentar).
Además, tenga en cuenta que no necesariamente se reduce a cuántos registros tiene, sino al tamaño de sus registros.
Por ejemplo, ¿ha considerado la diferencia de rendimiento entre 1,000 registros con 50 columnas cada uno versus 100,000 registros con solo 5 columnas cada uno?
Por último, ¿tal vez estás consultando / almacenando más datos de los que necesitas? Aquí hay una buena lectura sobre las estrategias de optimización de SQL . Limite la cantidad de datos que está extrayendo, especialmente si no lo está utilizando todo (algunos programadores SQL se vuelven perezosos y simplemente seleccionan todo aunque solo usen un pequeño subconjunto). No olvide que el analizador de consultas SQL también puede convertirse en su mejor amigo.
fuente
La tabla variable está disponible solo para la sesión actual, por ejemplo, si necesita
EXEC
otro procedimiento almacenado dentro del actual, tendrá que pasar la tabla ya queTable Valued Parameter
esto afectará el rendimiento, con tablas temporales con las que solo puede hacer esto. pasando el nombre de la tabla temporalPara probar una tabla temporal:
Para probar una tabla de variables:
Algo más que he experimentado es: si su esquema no tiene
GRANT
privilegios para crear tablas, use tablas variables.fuente
escribiendo datos en tablas declaradas
declare @tb
y después de unirme a otras tablas, me di cuenta de que el tiempo de respuesta en comparación con las tablas temporalestempdb .. # tb
es mucho mayor.Cuando me uno a ellos con @tb, el tiempo es mucho más largo para devolver el resultado, a diferencia de #tm , el retorno es casi instantáneo.
Hice pruebas con una unión de 10,000 filas y una con otras 5 tablas
fuente