CTE är långsammare eftersom det måste utföras oförändrat (via en CTE-skanning).
Det är alltså en optimeringsbarriär; för optimeraren är det inte tillåtet att demontera CTE, även om det skulle resultera i en smartare plan med samma resultat.
CTE-lösningen kan dock omstruktureras till en sammanfogad underfråga (liknande temptabellen i frågan). I postgres är en sammanfogad underfråga vanligtvis snabbare än varianten EXISTS() nuförtiden.
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
;
Ett annat sätt är att använda en TEMP VIEW
. Detta är syntaktisk motsvarande temp table
fall, men semantiskt likvärdigt med det sammanfogade underfrågeformuläret (de ger exakt samma frågeplan, åtminstone i det här fallet). Detta beror på att Postgress optimerare demonterar vyn och kombinerar den med huvudfrågan (pull-up ). Du kan se en view
som ett 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
);
[UPPDATERAD:Jag hade fel om att CTE alltid måste utföras till slutförande, vilket bara är fallet för datamodifierande CTE]