Au lieu de créer une nouvelle table, vous pouvez également réinsérer des lignes uniques dans la même table après l'avoir tronquée. Faites tout cela en une seule transaction . Si vous le souhaitez, vous pouvez supprimer automatiquement la table temporaire à la fin de la transaction avec ON COMMIT DROP
. Voir ci-dessous.
Cette approche n'est utile que s'il y a beaucoup de lignes à supprimer de partout dans la table. Pour quelques doublons, utilisez un simple DELETE
.
Vous avez mentionné des millions de lignes. Pour accélérer l'opération, vous souhaitez allouer suffisamment de tampons temporaires pour la session. Le paramètre doit être ajusté avant qu'un tampon temporaire ne soit utilisé dans votre session en cours. Découvrez la taille de votre table:
SELECT pg_size_pretty(pg_relation_size('tbl'));
Réglez en temp_buffers
conséquence. Arrondissez généreusement car la représentation en mémoire nécessite un peu plus de RAM.
SET temp_buffers = 200MB; -- example value
BEGIN;
-- CREATE TEMPORARY TABLE t_tmp ON COMMIT DROP AS -- drop temp table at commit
CREATE TEMPORARY TABLE t_tmp AS -- retain temp table after commit
SELECT DISTINCT * FROM tbl; -- DISTINCT folds duplicates
TRUNCATE tbl;
INSERT INTO tbl
SELECT * FROM t_tmp;
-- ORDER BY id; -- optionally "cluster" data while being at it.
COMMIT;
Cette méthode peut être supérieure à la création d'une nouvelle table si des objets dépendants existent. Vues, index, clés étrangères ou autres objets référençant la table. TRUNCATE
vous permet de commencer avec une ardoise vierge de toute façon (nouveau fichier en arrière-plan) et est beaucoup plus rapide qu'avec DELETE FROM tbl
de grandes tables ( DELETE
peut en fait être plus rapide avec de petites tables).
Pour les grandes tables, il est régulièrement plus rapide de supprimer les index et les clés étrangères, de remplir la table et de recréer ces objets. En ce qui concerne les contraintes fk, vous devez être certain que les nouvelles données sont bien sûr valides, sinon vous rencontrerez une exception en essayant de créer le fk.
Notez que cela TRUNCATE
nécessite un verrouillage plus agressif que DELETE
. Cela peut être un problème pour les tables à forte charge simultanée.
Si ce TRUNCATE
n'est pas une option ou généralement pour les tables petites à moyennes, il existe une technique similaire avec un CTE de modification des données (Postgres 9.1 +):
WITH del AS (DELETE FROM tbl RETURNING *)
INSERT INTO tbl
SELECT DISTINCT * FROM del;
-- ORDER BY id; -- optionally "cluster" data while being at it.
Plus lent pour les grandes tables, car TRUNCATE
c'est plus rapide là-bas. Mais peut-être plus rapide (et plus simple!) Pour les petites tables.
Si vous n'avez aucun objet dépendant du tout, vous pouvez créer une nouvelle table et supprimer l'ancienne, mais vous ne gagnerez pratiquement rien à cette approche universelle.
Pour les très grandes tables qui ne rentreraient pas dans la RAM disponible , la création d'une nouvelle table sera considérablement plus rapide. Vous devrez mettre cela en balance avec d'éventuels problèmes / frais généraux avec des objets dépendants.