sql >> Database >  >> RDS >> PostgreSQL

Garandeert postgres union de volgorde van uitvoering bij het aanroepen van functies met bijwerkingen?

In de praktijk zullen ze worden uitgevoerd in de aangegeven volgorde, maar er wordt geen garantie gegeven.

Als het gegarandeerd is, wordt het behandeld in de documentatie of de SQL-standaard. Ik zie geen enkele vermelding van de volgorde van uitvoering van een UNION in een van beide.

Als de optimizer een reden had om de ene voor de andere uit te voeren, zou het vrij zijn om dat te doen.

Voer instructies in de gewenste volgorde uit om de volgorde van uitvoering te garanderen:

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

Als u retourvluchten wilt verminderen, gebruik dan indien mogelijk de batchfaciliteiten van uw klant, of gebruik een DO blok:

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

Als u waarden moet retourneren, gebruik dan een functie en RETURN QUERY of RETURN NEXT .

Of u kunt bestellen met een CTE forceren, omdat in PostgreSQL (helaas) CTE's fungeren als optimalisatiehekken die materialisatie van resultaten afdwingen . AFAIK PostgreSQL hoeft de CTE-termen echter nog steeds niet uit te voeren in de volgorde waarin ze zijn geschreven of de volgorde waarin ze worden genoemd; de enige garantie die u krijgt is als u dit doet:

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

dan function1 moet eerst worden uitgevoerd en gerealiseerd. Dat is echter een PostgreSQL-specifieke fout; het is niet waar voor andere database-engines, niet gegarandeerd door de standaard, en je moet er niet op vertrouwen.

Dat geldt niet voor

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

... in dit geval kan PostgreSQL de onafhankelijke CTE-termen in willekeurige volgorde uitvoeren.

Ook bij joins geldt hetzelfde principe. Als termen onafhankelijk zijn, kan het systeem ervoor kiezen ze in willekeurige volgorde uit te voeren, hoewel dit over het algemeen niet het geval is. Dus:

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

zou kunnen evalueren en materialiseren bar() voeg dan de resultaten toe op foo() .

Als je geordende uitvoering wilt, moet je niet vertrouwen op vaste operaties zoals vakbonden en joins. Gebruik afzonderlijke zoekopdrachten of procedurecode.

Ja, dat is er.

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



  1. Automatische updates van statistieken bijhouden

  2. Hoe werkt een MYSQL Self-Join?

  3. Wat zijn de kosten van het indexeren van meerdere db-kolommen?

  4. Hoe de volledige MySQL-database te verwijderen