Las vistas en línea le permiten seleccionar de una subconsulta como si fuera una tabla diferente:
SELECT
*
FROM /* Selecting from a query instead of table */
(
SELECT
c1
FROM
t1
WHERE
c1 > 0
) a
WHERE
a.c1 < 50;
He visto esto referido al uso de diferentes términos: vistas en línea, cláusula WITH, CTE y tablas derivadas. Para mí parece que son diferentes sintaxis específica del proveedor para la misma cosa.
¿Es esta una suposición errónea? ¿Hay alguna diferencia técnica / de rendimiento entre estos?
oracle
cte
derived-tables
Kshitiz Sharma
fuente
fuente
WITH...
). Puede volver a escribir cada tabla derivada como CTE, pero tal vez no al revés (por ejemplo CTE recursiva o el uso de los CTE varias veces)Respuestas:
Existen algunas diferencias importantes entre las vistas en línea (tablas derivadas) y la cláusula WITH (CTE) en Oracle. Algunos de ellos son bastante universales, es decir, son aplicables a otros RDBMS.
WITH
se puede usar para crear subconsultas recursivas, vista en línea -no (por lo que sé, lo mismo es para todos los RDBMS que admiten CTE)WITH
cláusula es más probable que se ejecute físicamente primero; En muchos casos, elegir entreWITH
y la vista en línea hace que el optimizador elija diferentes planes de ejecución (supongo que es específico del proveedor, tal vez incluso de la versión).WITH
puede materializarse como una tabla temporal (no sé si algún otro proveedor pero Oracle admite esta función).WITH
puede hacer referencia a la subconsulta en varias veces, en otras subconsultas y en la consulta principal (verdadero para la mayoría de los RDBMS).fuente
LATERAL
se use.Otras respuestas cubren las diferencias de sintaxis bastante bien, así que no voy a entrar en eso. En cambio, esta respuesta solo cubrirá el rendimiento en Oracle.
El optimizador de Oracle puede optar por materializar los resultados de un CTE en una tabla temporal interna. Utiliza una heurística para hacer esto en lugar de la optimización basada en costos. La heurística es algo así como "Materializar el CTE si no es una expresión trivial y se hace referencia al CTE más de una vez en la consulta". Hay algunas consultas para las cuales la materialización mejorará el rendimiento. Hay algunas consultas para las cuales la materialización degradará drásticamente el rendimiento. El siguiente ejemplo es un poco artificial pero ilustra bien el punto:
Primero cree una tabla con una clave primaria que contenga enteros del 1 al 10000:
Considere la siguiente consulta que usa dos tablas derivadas:
Podemos ver esta consulta y determinar rápidamente que no devolverá ninguna fila. Oracle debería poder usar el índice para determinar eso también. En mi máquina, la consulta finaliza casi instantáneamente con el siguiente plan:
No me gusta repetirme, así que intentemos la misma consulta con un CTE:
Aquí está el plan:
Ese es un plan realmente malo. En lugar de usar el índice, Oracle materializa 10000 X 10000 = 100000000 filas en una tabla temporal solo para eventualmente devolver 0 filas. El costo de este plan es de alrededor de 6 M, que es mucho más alto que la otra consulta. La consulta tardó 68 segundos en finalizar en mi máquina.
Tenga en cuenta que la consulta podría haber fallado si no hay suficiente memoria o espacio libre en el espacio de tabla temporal.
Puedo usar la
INLINE
sugerencia no documentada para evitar que el optimizador materialice el CTE:Esa consulta puede usar el índice y finaliza casi al instante. El costo de la consulta es el mismo que antes, 11. Entonces, para la segunda consulta, la heurística utilizada por Oracle resultó en que eligiera una consulta con un costo estimado de 6 M en lugar de una consulta con un costo estimado de 11.
fuente
Para SQL Server,
WITH CTE
especifica el conjunto de resultados con nombre temporal, pero solo se requiere para el primeroCTE
. es decirPero esto no es una subconsulta o una subconsulta correlacionada. Hay cosas que puede hacer con un CTE que no puede hacer con una subconsulta en SQL Server, como actualizar las Tablas a las que se hace referencia en un CTE. Aquí hay un ejemplo de actualización de una tabla con un CTE.
Una subconsulta sería algo así como
O una subconsulta correlacionada es lo que ha proporcionado en su OP si tuviera que hacer referencia / unirse / limitar sus resultados según a.c1.
Por lo tanto, definitivamente no son lo mismo, aunque en muchos casos podría usar uno o más de estos métodos para lograr el mismo resultado. Solo depende de cuál sea el resultado final.
fuente
La principal diferencia entre la
with
cláusula y una subconsulta en Oracle es que puede hacer referencia a una consulta dentro de la cláusula varias veces. A continuación, puede hacer algunas optimizaciones con él, como convertirlo en una tabla temporal con unamaterialize
sugerencia. También puede hacer consultas recursivas con ella haciendo referencia a sí misma dentro de unawith
cláusula. No puede hacer eso con una vista en línea.Se puede encontrar más información aquí y aquí .
fuente
MATERIALIZE
resp.INLINE
por lo contrariomaterialize
sugerencia es una opción válida. A veces necesitaba especificarlo al optimizar consultas muy complejas donde sabía que materializar el CTE beneficiaría el plan de ejecución.Debe tener cuidado con los CTE en el servidor SQL, no solo con Oracle, hay casos en los que las consultas funcionan mucho peor cuando se usan CTE en comparación con las subconsultas, la aplicación cruzada, etc.
Como siempre, es importante probar cualquier consulta en varias condiciones de carga para determinar cuál funciona mejor.
Al igual que @scsimon con Oracle, a veces el servidor MS SQL no hace lo que espera con respecto al uso del índice.
Si va a usar los mismos datos más de una vez, los CTE pueden ser más útiles, si solo los usa una vez, a menudo una subconsulta es más rápida en grandes conjuntos de datos.
por ejemplo, seleccione * de (mi subconsulta) unirse a otra cosa ...
fuente