¿Cuál es la diferencia entre una expresión de tabla común (CTE) y una tabla temporal? ¿Y cuándo debo usar uno sobre el otro?
CTE
WITH cte (Column1, Column2, Column3)
AS
(
SELECT Column1, Column2, Column3
FROM SomeTable
)
SELECT * FROM cte
Tabla de temperatura
SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable
SELECT * FROM #tmpTable
sql-server
cte
Rachel
fuente
fuente
Respuestas:
Esto es bastante amplio, pero le daré una respuesta lo más general posible.
CTE ...
VIEW
s#Tablas de temperatura ...
En cuanto a cuándo usar cada uno, tienen casos de uso muy diferentes. Si va a tener un conjunto de resultados muy grande, o necesita referirse a él más de una vez, póngalo en una
#temp
tabla. Si necesita ser recursivo, es desechable o es simplemente para simplificar algo lógicamente,CTE
se prefiere a.Además, una
CTE
debe nunca serán usados para el rendimiento . Casi nunca acelerarás las cosas usando un CTE, porque, de nuevo, es solo una vista desechable. Puede hacer algunas cosas interesantes con ellos, pero acelerar una consulta no es realmente una de ellas.fuente
EDITAR:
Por favor, vea los comentarios de Martin a continuación:
Respuesta original
CTE
Leer más en MSDN
Un CTE crea la tabla que se usa en la memoria, pero solo es válida para la consulta específica que le sigue. Cuando se utiliza la recursividad, esta puede ser una estructura efectiva.
También es posible que desee considerar el uso de una variable de tabla. Esto se usa como una tabla temporal y se puede usar varias veces sin necesidad de volver a materializarse para cada unión. Además, si necesita conservar algunos registros ahora, agregue algunos registros más después de la siguiente selección, agregue algunos registros más después de otra operación, luego devuelva esos pocos registros, entonces esta puede ser una estructura práctica, ya que no No es necesario dejarlo caer después de la ejecución. Principalmente solo azúcar sintáctico. Sin embargo, si mantiene bajo el recuento de filas, nunca se materializa en el disco. Consulte ¿Cuál es la diferencia entre una tabla temporal y una variable de tabla en SQL Server? para más detalles.
Tabla de temperatura
Lea más en MSDN: desplácese hacia abajo aproximadamente el 40% del camino
Una tabla temporal es literalmente una tabla creada en el disco, solo en una base de datos específica que todos saben que se puede eliminar. Es responsabilidad de un buen desarrollador destruir esas tablas cuando ya no son necesarias, pero un DBA también puede borrarlas.
Las tablas temporales vienen en dos variedades: local y global. En términos de MS Sql Server, utiliza una
#tableName
designación para local y una##tableName
designación para global (tenga en cuenta el uso de un solo o doble # como característica de identificación).Tenga en cuenta que con las tablas temporales, a diferencia de las variables de tabla o CTE, puede aplicar índices y similares, ya que estas son legítimamente tablas en el sentido normal de la palabra.
En general, usaría tablas temporales para consultas más largas o más grandes, y CTE o variables de tabla si ya tuviera un conjunto de datos pequeño y quisiera escribir rápidamente un poco de código para algo pequeño. La experiencia y los consejos de otros indican que debe usar CTE donde tiene un pequeño número de filas devueltas. Si tiene un gran número, probablemente se beneficiaría de la capacidad de indexar en la tabla temporal.
fuente
SELECT Column1, Column2, Column3 FROM SomeTable
WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X
, también verifique los planes de ejecución. Aunque a veces es posible hackear el plan para obtener un carrete. Hay un elemento de conexión que solicita una pista para esto.La respuesta aceptada aquí dice que "un CTE nunca debe usarse para el rendimiento", pero eso podría inducir a error. En el contexto de CTE versus tablas temporales, acabo de terminar de eliminar una gran cantidad de basura de un conjunto de procesos almacenados porque algunos tontos deben haber pensado que había poca o ninguna sobrecarga al usar tablas temporales. Metí el lote en los CTE, excepto aquellos que legítimamente iban a ser reutilizados durante todo el proceso. Obtuve aproximadamente un 20% de rendimiento en todas las métricas. Luego me puse a eliminar todos los cursores que intentaban implementar el procesamiento recursivo. Aquí fue donde vi la mayor ganancia. Terminé recortando los tiempos de respuesta por un factor de diez.
Los CTE y las tablas temporales tienen casos de uso muy diferentes. Solo quiero enfatizar que, aunque no es una panacea, la comprensión y el uso correcto de los CTE pueden conducir a algunas mejoras verdaderamente estelares tanto en la calidad / mantenimiento del código como en la velocidad. Desde que los manejé, veo las tablas temporales y los cursores como los grandes males del procesamiento de SQL. Puedo pasar bien con las variables de tabla y CTE para casi todo ahora. Mi código es más limpio y rápido.
fuente
Se puede llamar a un CTE repetidamente dentro de una consulta y se evalúa cada vez que se hace referencia a él; este proceso puede ser recursivo. Si solo se hace referencia una vez, se comporta como una subconsulta, aunque los CTE se pueden parametrizar.
Una tabla temporal persiste físicamente y puede indexarse. En la práctica, el optimizador de consultas también puede persistir resultados intermedios de unión o subconsulta en segundo plano, como en operaciones de spool, por lo que no es estrictamente cierto que los resultados de los CTE nunca se conserven en el disco.
Las variables de la tabla IIRC (por otro lado) son siempre estructuras en memoria.
fuente
La tabla temporal es un objeto real en tempdb, pero cte es solo una especie de contenedor alrededor de consultas complejas para simplificar la sintaxis de la recursividad organizada en un solo paso.
fuente
La razón principal para usar CTE es acceder a las funciones de la ventana, como
row_number()
y varias otras.Esto significa que puede hacer cosas como obtener la primera o la última fila por grupo MUY MUY MUY rápido y eficiente, más eficiente que otros medios en la mayoría de los casos prácticos .
Puede ejecutar una consulta similar a la anterior utilizando una subconsulta correlacionada o utilizando una subconsulta, pero el CTE será más rápido en casi todos los escenarios.
Además, los CTE realmente pueden ayudar a simplificar su código. Esto puede generar ganancias de rendimiento porque comprende mejor la consulta y puede introducir más lógica de negocios para ayudar al optimizador a ser más selectivo.
Además, los CTE pueden aumentar el rendimiento si comprende su lógica empresarial y sabe qué partes de la consulta deben ejecutarse primero; por lo general, coloque primero sus consultas más selectivas que conducen a conjuntos de resultados que pueden usar un índice en su próxima unión y agregar la
option(force order)
consulta insinuaciónFinalmente, los CTE no usan tempdb de forma predeterminada, por lo que reduce la contención en ese cuello de botella a través de su uso.
Las tablas temporales se deben usar si necesita consultar los datos varias veces, o alternativamente si mide sus consultas y descubre eso al insertarlas en una tabla temporal y luego agregar un índice para mejorar su rendimiento.
fuente
Parece que hay un poco de negatividad aquí hacia los CTE.
Entiendo que un CTE es básicamente una especie de vista ad hoc. SQL es tanto un lenguaje declarativo como un lenguaje basado en conjuntos. ¡Los CTE son una excelente manera de declarar un conjunto! ¡No poder indexar un CTE es realmente algo bueno porque no es necesario! Realmente es una especie de azúcar sintáctica para facilitar la lectura / escritura de la consulta. Cualquier optimizador decente resolverá el mejor plan de acceso utilizando índices en las tablas subyacentes. Esto significa que podría acelerar de manera efectiva su consulta CTE siguiendo los consejos del índice en las tablas subyacentes.
Además, solo porque haya definido un conjunto como CTE, no significa que todas las filas del conjunto deban procesarse. Dependiendo de la consulta, el optimizador puede procesar filas "suficientes" para satisfacer la consulta. Tal vez solo necesitabas los primeros 20 más o menos para tu pantalla. Si creó una tabla temporal, ¡realmente necesita leer / escribir todas esas filas!
Basado en esto, diría que los CTE son una gran característica de SQL y se pueden usar en cualquier lugar que faciliten la lectura de la consulta. Solo pensaría en una tabla temporal para un proceso por lotes que realmente necesitaría procesar cada registro. Incluso entonces afaik no se recomienda realmente porque en una tabla temporal es mucho más difícil para la base de datos ayudarlo con el almacenamiento en caché y los índices. Sería mejor tener una tabla permanente con un campo PK exclusivo para su transacción.
Tengo que admitir que mi experiencia es principalmente con DB2, así que supongo que CTE funciona de manera similar en ambos productos. Estaré felizmente corregido si los CTE son de alguna manera inferiores en el servidor SQL. ;)
fuente