CTE je pomalejší, protože musí být proveden beze změny (prostřednictvím skenování CTE).
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]