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

Meilleur moyen de supprimer des millions de lignes par ID

Tout dépend...

  • En supposant aucun accès en écriture simultané aux tables impliquées ou vous devrez peut-être verrouiller les tables exclusivement ou cet itinéraire peut ne pas vous convenir du tout.

  • Supprimez tous les index (éventuellement sauf ceux nécessaires à la suppression elle-même).
    Recréez-les ensuite. C'est généralement beaucoup plus rapide que les mises à jour incrémentielles des index.

  • Vérifiez si vous avez des déclencheurs qui peuvent être supprimés/désactivés temporairement en toute sécurité.

  • Les clés étrangères référencent-elles votre table ? Peuvent-ils être supprimés ? Temporairement supprimé ?

  • En fonction de vos paramètres de vide automatique, il peut aide pour exécuter VACUUM ANALYZE avant l'opération.

  • Certains des points listés dans le chapitre correspondant du manuel Remplir une base de données peut également être utile, selon votre configuration.

  • Si vous supprimez de grandes parties du tableau et que le reste tient dans la RAM, le moyen le plus rapide et le plus simple peut être celui-ci :

BEGIN; -- typically faster and safer wrapped in a single transaction

SET LOCAL temp_buffers = '1000MB'; -- enough to hold the temp table

CREATE TEMP TABLE tmp AS
SELECT t.*
FROM   tbl t
LEFT   JOIN del_list d USING (id)
WHERE  d.id IS NULL;      -- copy surviving rows into temporary table

TRUNCATE tbl;             -- empty table - truncate is very fast for big tables

INSERT INTO tbl
SELECT * FROM tmp;        -- insert back surviving rows.
-- ORDER BY ?             -- optionally order favorably while being at it

COMMIT;

De cette façon, vous n'avez pas à recréer des vues, des clés étrangères ou d'autres objets dépendants. Et vous obtenez une table vierge (triée) sans ballonnement.

En savoir plus sur les temp_buffers réglage dans le manuel. Cette méthode est rapide tant que la table tient dans la mémoire, ou du moins la plus grande partie. Le wrapper de transaction protège contre la perte de données si votre serveur tombe en panne au milieu de cette opération.

Exécutez VACUUM ANALYZE ensuite. Ou VACUUM FULL ANALYZE si vous voulez l'amener à la taille minimale (prend un verrou exclusif). Pour les grandes tables, considérez les alternatives CLUSTER / pg_repack ou similaire :

  • Optimiser la plage de requêtes d'horodatage Postgres

Pour les petits tableaux, un simple DELETE au lieu de TRUNCATE est souvent plus rapide :

DELETE FROM tbl t
USING  del_list d
WHERE  t.id = d.id;

Lire les Remarques section pour TRUNCATE dans le manuel. En particulier (comme Pedro l'a également souligné dans son commentaire) :

TRUNCATE ne peut pas être utilisé sur une table contenant des références de clé étrangère provenant d'autres tables, à moins que toutes ces tables ne soient également tronquées dans la même commande. [...]

Et :

TRUNCATE ne déclenchera aucun ON DELETE déclencheurs qui pourraient exister pour les tables.