CTE lebih lambat karena harus dijalankan tanpa perubahan (melalui pemindaian CTE).
Dengan demikian, ini merupakan penghalang pengoptimalan; untuk pengoptimal, pembongkaran CTE tidak diperbolehkan, meskipun itu akan menghasilkan rencana yang lebih cerdas dengan hasil yang sama.
Solusi CTE dapat difaktorkan ulang menjadi subquery yang digabungkan (mirip dengan tabel temp dalam pertanyaan). Di postgres, subquery yang digabungkan biasanya lebih cepat daripada varian EXISTS() saat ini.
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
;
Cara lain adalah dengan menggunakan TEMP VIEW
. Ini secara sintaksis setara dengan temp table
kasus, tapi secara semantik setara dengan formulir subkueri gabungan (mereka menghasilkan tepat rencana kueri yang sama, setidaknya dalam kasus ini). Ini karena pengoptimal Postgres membongkar tampilan dan menggabungkannya dengan kueri utama (pull-up ). Anda dapat melihat view
sebagai semacam makro di 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
);
[DIPERBARUI:Saya salah tentang CTE yang harus selalu dieksekusi hingga selesai, yang hanya berlaku untuk CTE yang memodifikasi data]