PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Supprimer en utilisant CTE plus lentement qu'en utilisant la table temporaire dans Postgres

Le CTE est plus lent car il doit être exécuté tel quel (via un scan CTE).

TFM (section 7.8.2) indique : Les instructions de modification de données dans WITH sont exécutées exactement une fois, et toujours jusqu'à la fin, indépendamment du fait que la requête principale lit tout (ou même une partie) de leur sortie. Notez que cela est différent de la règle pour SELECT dans WITH :comme indiqué dans la section précédente, l'exécution d'un SELECT est transporté uniquement dans la mesure où la requête principale exige sa sortie.

C'est donc une barrière d'optimisation; pour l'optimiseur, le démantèlement du CTE n'est pas autorisé, même si cela se traduirait par un plan plus intelligent avec les mêmes résultats.

La solution CTE peut cependant être refactorisée en une sous-requête jointe (similaire à la table temporaire de la question). Dans postgres, une sous-requête jointe est généralement plus rapide que la variante EXISTS(), de nos jours.

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
        ;

Une autre méthode consiste à utiliser une TEMP VIEW . C'est syntaxiquement équivalent à la temp table cas, mais sémantiquement équivalent à la forme de sous-requête jointe (ils donnent exactement le même plan de requête, du moins dans ce cas). C'est parce que l'optimiseur de Postgres démonte la vue et la combine avec la requête principale (pull-up ). Vous pourriez voir une view comme une sorte de macro dans 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
        );

[MISE À JOUR :Je me suis trompé sur le fait que les CTE doivent toujours être exécutés jusqu'à leur achèvement, ce qui n'est le cas que pour les CTE qui modifient les données]