CTE'en er langsommere, fordi den skal udføres uændret (via en CTE-scanning).
Det er således en optimeringsbarriere; for optimizeren er det ikke tilladt at afmontere CTE, selvom det ville resultere i en smartere plan med de samme resultater.
CTE-løsningen kan dog omdannes til en samlet underforespørgsel (svarende til temp-tabellen i spørgsmålet). I postgres er en sammenføjet underforespørgsel normalt hurtigere end EXISTS()-varianten i dag.
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
;
En anden måde er at bruge en TEMP VIEW
. Dette er syntaktisk svarende til temp table
case, men semantisk svarende til den samlede underforespørgselsformular (de giver præcis den samme forespørgselsplan, i det mindste i dette tilfælde). Dette skyldes, at Postgres' optimering afmonteres visningen og kombinerer den med hovedforespørgslen (pull-up ). Du kunne se en view
som en slags makro i 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
);
[OPDATERET:Jeg tog fejl om, at CTE'er altid skal udføres-til-fuldførelse, hvilket kun er tilfældet for datamodificerende CTE'er]