sql >> Base de Datos >  >> RDS >> PostgreSQL

¿Postgres union garantiza el orden de ejecución al invocar funciones con efectos secundarios?

En la práctica se ejecutarán en el orden indicado, pero no se garantiza.

Si está garantizado, estará cubierto en la documentación o en el estándar SQL. No veo ninguna mención del orden de ejecución de un UNION en cualquiera.

Si el optimizador tuviera una razón para ejecutar uno antes que el otro, sería libre de hacerlo.

Para garantizar el orden de ejecución, ejecute las sentencias en el orden deseado:

SELECT * FROM func1();
SELECT * FROM func2();

Si desea reducir los viajes de ida y vuelta, use las instalaciones de procesamiento por lotes de su cliente si es posible, o use un DO bloque:

DO
$$
BEGIN
  PERFORM proc1();
  PERFORM proc2();
END;
$$;

Si necesita devolver valores, use una función y RETURN QUERY o RETURN NEXT .

O puede forzar el pedido con un CTE, porque en PostgreSQL (desafortunadamente) CTE actúan como vallas de optimización que fuerzan la materialización de los resultados . Sin embargo, AFAIK PostgreSQL aún no tiene que ejecutar los términos CTE en el orden en que están escritos o en el orden en que se hace referencia; la única garantía que obtienes es si haces esto:

WITH f1 AS (SELECT * FROM function1())
SELECT * FROM function2()
UNION ALL
SELECT * FROM f1;

entonces function1 debe ejecutarse y materializarse primero. Sin embargo, esa es una falla específica de PostgreSQL; no es cierto para otros motores de base de datos, no está garantizado por el estándar, y no debe confiar en él.

Eso no se extiende a

WITH f1 AS (SELECT * FROM function1())
     f2 AS (SELECT * FROM function2())
SELECT * FROM f2
UNION ALL
SELECT * FROM f1;

... como en este caso, PostgreSQL puede ejecutar los términos CTE independientes en cualquier orden.

Nuevamente, con las uniones, se aplica el mismo principio. Si los términos son independientes, el sistema puede optar por ejecutarlos en cualquier orden, aunque generalmente no lo hará. Entonces:

select null::void from (select 1 from foo() ) left join (select 1 from bar()) on true

podría evaluar y materializar bar() luego únete a sus resultados en foo() .

Si desea una ejecución ordenada, no debe depender de operaciones de conjuntos como uniones y uniones. Use consultas separadas o código de procedimiento.

Sí, lo hay.

SELECT * FROM function1();
SELECT * FROM function2();