Anstatt eine neue Tabelle zu erstellen, können Sie auch eindeutige Zeilen nach dem Abschneiden wieder in dieselbe Tabelle einfügen. Machen Sie alles in einer Transaktion . Optional können Sie die temporäre Tabelle am Ende der Transaktion automatisch mit löschen ON COMMIT DROP
. Siehe unten.
Dieser Ansatz ist nur nützlich, wenn in der gesamten Tabelle viele Zeilen gelöscht werden müssen. Verwenden Sie für nur wenige Duplikate eine EbeneDELETE
.
Sie haben Millionen von Zeilen erwähnt. Um den Vorgang zu beschleunigen , möchten Sie genügend temporäre Puffer für die Sitzung zuweisen . Die Einstellung muss angepasst werden, bevor in Ihrer aktuellen Sitzung ein temporärer Puffer verwendet wird. Finden Sie die Größe Ihres Tisches heraus:
SELECT pg_size_pretty(pg_relation_size('tbl'));
temp_buffers
Entsprechend einstellen . Großzügig aufrunden, da die In-Memory-Darstellung etwas mehr RAM benötigt.
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;
Diese Methode kann dem Erstellen einer neuen Tabelle überlegen sein, wenn abhängige Objekte vorhanden sind. Ansichten, Indizes, Fremdschlüssel oder andere Objekte, die auf die Tabelle verweisen. TRUNCATE
Sie beginnen ohnehin mit einer sauberen Tafel (neue Datei im Hintergrund) und sind viel schneller als DELETE FROM tbl
bei großen Tabellen ( DELETE
können bei kleinen Tabellen sogar schneller sein).
Bei großen Tabellen ist es regelmäßig schneller , Indizes und Fremdschlüssel zu löschen, die Tabelle neu zu füllen und diese Objekte neu zu erstellen. In Bezug auf fk-Einschränkungen müssen Sie natürlich sicher sein, dass die neuen Daten gültig sind. Andernfalls tritt beim Versuch, fk zu erstellen, eine Ausnahme auf.
Beachten Sie, dass TRUNCATE
eine aggressivere Verriegelung erforderlich ist als DELETE
. Dies kann ein Problem für Tabellen mit hoher gleichzeitiger Belastung sein.
Wenn dies TRUNCATE
keine Option ist oder generell für kleine bis mittlere Tabellen gilt, gibt es eine ähnliche Technik mit einem datenmodifizierenden CTE (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.
Langsamer für große Tische, weil TRUNCATE
es dort schneller ist. Kann aber für kleine Tische schneller (und einfacher!) Sein.
Wenn Sie überhaupt keine abhängigen Objekte haben, können Sie eine neue Tabelle erstellen und die alte löschen, aber Sie gewinnen kaum etwas über diesen universellen Ansatz.
Bei sehr großen Tabellen, die nicht in den verfügbaren Arbeitsspeicher passen , ist das Erstellen einer neuen Tabelle erheblich schneller. Sie müssen dies gegen mögliche Probleme / Overhead mit abhängigen Objekten abwägen.