Je me demande quel serait le moyen le plus efficace de supprimer un grand nombre de lignes de PostgreSQL, ce processus ferait partie d'une tâche récurrente chaque jour pour importer en masse des données (un delta d'insertions + suppressions) dans une table. Il pourrait y avoir des milliers, voire des millions de lignes à supprimer.
J'ai un fichier de clés primaires, un par ligne. Les deux options auxquelles je pensais étaient dans le sens de ce qui suit, mais je ne connais pas / ne comprends pas suffisamment les internes de PostgreSQL pour prendre une décision éclairée qui serait la meilleure.
- Exécutez une
DELETE
requête pour chaque ligne du fichier, avec une simpleWHERE
clé primaire (ou regroupez les suppressions par lots enn
utilisant uneIN()
clause) - Importez les clés primaires dans une table temporaire à l'aide de la
COPY
commande, puis supprimez-les de la table principale à l'aide d'une jointure
Toutes les suggestions seront très appréciées!
postgresql
delete
bulk
tarnfeld
la source
la source
Réponses:
Votre deuxième option est beaucoup plus propre et fonctionnera assez bien pour que cela en vaille la peine. Votre alternative est de construire des requêtes gigantesques qui seront assez pénibles à planifier et à exécuter. En général, vous feriez mieux de laisser PostgreSQL faire le travail ici. En général, j'ai trouvé des mises à jour sur des dizaines de milliers de lignes de la manière que vous décrivez pour fonctionner correctement, mais il y a une chose importante à éviter.
La façon de le faire est d'utiliser une sélection et une jointure dans votre suppression.
Vous ne devez en aucun cas procéder comme suit avec une grande table:
Cela provoquera généralement une boucle anti-jointure imbriquée qui rendra les performances plutôt problématiques. Si vous finissez par emprunter cette voie, faites-le à la place:
PostgreSQL est généralement assez bon pour éviter les mauvais plans, mais il existe encore des cas impliquant des jointures externes qui peuvent faire une grande différence entre les bons et les mauvais plans.
Cela se promène un peu plus loin, mais je pense que cela vaut la peine d'être mentionné en raison de la facilité avec laquelle il est possible de passer de IN à NOT IN et de regarder le réservoir de performances de requête.
la source
IN ( select id from foo except select id from rows_to_keep )
voir postgresql.org/docs/9.4/static/queries-union.htmlJe suis tombé sur cette question parce que j'avais un problème similaire. Je nettoie une base de données qui compte plus de 300 millions de lignes, la base de données finale ne contiendra qu'environ 30% des données d'origine. Si vous êtes confronté à un scénario similaire, il est en fait plus facile d'insérer dans une nouvelle table et de réindexer au lieu de supprimer.
Faites quelque chose comme
Avec une indexation correcte sur foo et bar, vous pouvez éviter les analyses Seq.
Ensuite, vous devrez réindexer et renommer la table.
la source