CTEは、変更せずに(CTEスキャンを介して)実行する必要があるため、低速です。
TFM(セクション7.8.2)は次のように述べています。
したがって、これは最適化の障壁です。;オプティマイザーの場合、同じ結果でよりスマートな計画が得られたとしても、CTEを解体することは許可されていません。
ただし、CTEソリューションは結合されたサブクエリにリファクタリングできます(質問の一時テーブルと同様)。 postgresでは、結合されたサブクエリは通常、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
;
もう1つの方法は、TEMP VIEW
を使用することです。 。これは構文的に temp table
と同等 ケースですが、意味論的に 結合されたサブクエリフォームと同等です(正確に 少なくともこの場合は、同じクエリプラン)。これは、Postgresのオプティマイザーが解体するためです。 ビューを表示し、メインクエリと組み合わせます(プルアップ )。 view
が表示されます 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
);
[更新:CTEを常に実行して完了する必要があることについて間違っていました。これは、データを変更するCTEの場合のみです]