sql >> Databáze >  >> RDS >> PostgreSQL

Odstraňte pomocí CTE pomaleji než pomocí dočasné tabulky v Postgresu

CTE je pomalejší, protože musí být proveden beze změny (prostřednictvím skenování CTE).

TFM (část 7.8.2) uvádí: Provádějí se příkazy upravující data ve WITH přesně jednou a vždy až do konce, nezávisle na tom, zda primární dotaz čte všechny (nebo dokonce jakýkoli) jejich výstup. Všimněte si, že se to liší od pravidla pro SELECT v WITH:jak bylo uvedeno v předchozí části, provedení SELECT je přenášeny pouze do té míry, pokud primární dotaz vyžaduje jeho výstup.

Jde tedy ooptimalizační bariéru; pro optimalizátor není demontáž CTE povolena, i když by to vedlo k chytřejšímu plánu se stejnými výsledky.

Řešení CTE však lze refaktorovat do spojeného poddotazu (podobně jako u dočasné tabulky v otázce). V postgresu je dnes spojený poddotaz obvykle rychlejší než varianta EXISTS().

DELETE FROM customer del
USING ( SELECT id
        , row_number() over(partition by uuid order by created_date desc)
                 as rn
        FROM customer
        ) sub
WHERE sub.id = del.id
AND sub.rn > 1
        ;

Dalším způsobem je použití TEMP VIEW . Toto je syntakticky ekvivalentní temp table případ, ale sémanticky ekvivalentní formuláři spojeného poddotazu (vynášejí přesně stejný plán dotazů, alespoň v tomto případě). Je to proto, že optimalizátor Postgres demontuje zobrazení a zkombinuje jej s hlavním dotazem (pull-up ). Můžete vidět view jako druh makra v PG.

CREATE TEMP VIEW targets
AS SELECT id
        , row_number() over(partition by uuid ORDER BY created_date DESC) AS rn
FROM customer;

EXPLAIN
DELETE FROM customer
WHERE id IN ( SELECT id
            FROM targets
            WHERE rn > 1
        );

[AKTUALIZOVÁNO:Mýlil jsem se v tom, že CTE musí být vždy provedeny do dokončení, což platí pouze pro CTE upravující data]



  1. SQL Query funguje na pracovní ploše, ale v jazyce Java poskytuje chybu syntaxe

  2. MySQL dotaz INNER JOIN s aliasy

  3. Laravel výmluvný stavitel dotazů - Součet se skupinou na vztahu

  4. Migrace SQL Django pro podmíněné spouštěče