La cláusula WITH permite definir consultas auxiliares (CTE) para organizar y reutilizar código SQL (y ya la vimos en otro post). Sin embargo, una consulta más legible no necesariamente es una consulta más rápida.
En Oracle, el impacto depende de cómo el optimizador ejecute la consulta.
1. Cuando usamos WITH una sola vez
Consideremos esta consulta:
WITH ventas_filtradas AS (
SELECT *
FROM ventas
WHERE fecha >= DATE '2026-01-01'
)
SELECT *
FROM ventas_filtradas
WHERE cliente_id = 10;
Podemos escribirla directamente:
SELECT *
FROM ventas
WHERE fecha >= DATE '2026-01-01'
AND cliente_id = 10;
Si Oracle integra la CTE en la consulta principal, ambas pueden generar el mismo plan de ejecución.
Pero si decide materializar la CTE, deberá generar y almacenar temporalmente sus resultados antes de utilizarlos. Esto puede agregar lecturas, escrituras y consumo de recursos innecesarios.
Cuando una CTE se utiliza una sola vez, materializarla puede representar un costo adicional sin aportar beneficios.
2. ¿Qué sucede con UNION?
Supongamos que necesitamos consultar dos grupos de clientes:
WITH datos AS (
SELECT *
FROM ventas
WHERE fecha >= DATE '2026-01-01'
)
SELECT *
FROM datos
WHERE cliente_id = 10
UNION
SELECT *
FROM datos
WHERE cliente_id = 20;
Si Oracle materializa datos, podría generar primero un conjunto grande de resultados y después aplicar los filtros de cada rama.
En determinados escenarios, esto resulta menos eficiente que ejecutar las consultas con sus filtros integrados, permitiendo al optimizador reducir los datos procesados.
Además, UNION elimina duplicados. Esta operación puede requerir ordenamiento o hashing y consumir recursos adicionales.
Si no necesitamos eliminar duplicados, podemos utilizar UNION ALL:
SELECT *
FROM ventas
WHERE fecha >= DATE '2026-01-01'
AND cliente_id = 10
UNION ALL
SELECT *
FROM ventas
WHERE fecha >= DATE '2026-01-01'
AND cliente_id = 20;
Esto evita el trabajo de deduplicación, aunque no garantiza por sí solo que la consulta sea más rápida.
3. ¿Cómo comprobarlo?
En Oracle, podemos analizar el plan real de ejecución:
SELECT *
FROM TABLE(
DBMS_XPLAN.DISPLAY_CURSOR(
NULL,
NULL,
'ALLSTATS LAST'
)
);
Conviene observar las operaciones TEMP ATBLE TRANSFORMATION y LOAD AS SELECT, además de las filas procesadas, los bloques leídos y el tiempo de ejecución.
- WITH mejora la legibilidad y facilita el mantenimiento.
- Materializar una CTE utilizada una sola vez puede agregar trabajo innecesario.
- Reutilizar una CTE puede evitar cálculos repetidos, pero depende del plan elegido.
- Con UNION, hay que considerar tanto la materialización como el costo de eliminar duplicados.
La regla de oro: no optimices por la apariencia del SQL. En Oracle, compará los planes de ejecución y medí el costo real antes de decidir qué alternativa es mejor.
No hay comentarios.:
Publicar un comentario