EXISTS
est simple et parmi les plus rapides pour la plupart des distributions de données :
DELETE FROM dupes d
WHERE EXISTS (
SELECT FROM dupes
WHERE key = d.key
AND ctid < d.ctid
);
À partir de chaque ensemble de lignes dupliquées (définies par des key
), ce qui permet de conserver la ligne avec le minimum de ctid
.
Le résultat est identique à celui de la réponse actuellement acceptée par a_horse . Juste plus rapide porque EXISTS
peut cesser d'évaluer dès que la première ligne incriminée est trouvée, alors que l'alternative avec min()
doit prendre en compte tous lignes par groupe pour calculer le minimum. La vitesse n'est pas une préoccupation pour les cette question, mais pourquoi ne pas l'accepter ?
Vous pouvez ajouter un UNIQUE
contrainte après le nettoyage, afin d'éviter que les doublons ne réapparaissent :
ALTER TABLE dupes ADD CONSTRAINT constraint_name_here UNIQUE (key);
À propos de la colonne du système ctid
:
Si une autre colonne est définie UNIQUE NOT NULL
dans le tableau (comme un PRIMARY KEY
), alors utilisez-le à la place de ctid
.
Si key
peut être NULL
et que vous n'en voulez qu'un seul, utilisez IS NOT DISTINCT FROM
au lieu de =
. Voir :
Comme c'est plus lent, vous pourriez plutôt exécuter la requête ci-dessus telle quelle, et ceci en plus :
DELETE FROM dupes d
WHERE key IS NULL
AND EXISTS (
SELECT FROM dupes
WHERE key IS NULL
AND ctid < d.ctid
);
Et réfléchissez :
Pour les petites tables, index n'améliorent généralement pas les performances. Il n'est pas nécessaire de chercher plus loin.
Para grandes tables y peu les doublons, un index existant sur (key)
peut aider (beaucoup).
Para principalement des doublons Un index peut être plus coûteux que bénéfique, car il doit être mis à jour en même temps. La recherche de doublons sans index est de toute façon plus rapide, car il y en a beaucoup et les doublons sont plus nombreux. EXISTS
Il suffit d'en trouver un. Mais considérez un une approche totalement différente si vous pouvez vous le permettre (c'est-à-dire si l'accès simultané le permet) : Écrire les quelques lignes survivantes dans une nouvelle table. Cela permet également d'éliminer le gonflement de la table (et de l'index) dans le processus. Voir :