Ich frage mich, wie man am effizientesten eine große Anzahl von Zeilen aus PostgreSQL löschen kann. Dieser Vorgang ist Teil einer täglichen wiederkehrenden Aufgabe, um Daten (ein Delta aus Einfügungen und Löschungen) in eine Tabelle zu importieren. Möglicherweise müssen Tausende, möglicherweise Millionen Zeilen gelöscht werden.
Ich habe eine Datei mit Primärschlüsseln, eine pro Zeile. Die beiden Optionen, über die ich nachgedacht habe, sind im folgenden Sinne, aber ich kenne / verstehe die Interna von PostgreSQL nicht genug, um eine fundierte Entscheidung zu treffen, die am besten wäre.
- Führen Sie eine
DELETE
Abfrage für jede Zeile in der Datei mit einem einfachenWHERE
Primärschlüssel aus (oder gruppieren Sie die Löschvorgänge in Gruppen,n
indem Sie eineIN()
Klausel verwenden). - Importieren Sie die Primärschlüssel mithilfe des
COPY
Befehls in eine temporäre Tabelle und löschen Sie sie anschließend mithilfe eines Joins aus der Haupttabelle
Anregungen werden sehr geschätzt!
postgresql
delete
bulk
Tarnfeld
quelle
quelle
Antworten:
Ihre zweite Option ist weitaus sauberer und wird gut genug abschneiden, damit es sich lohnt. Ihre Alternative besteht darin, gigantische Abfragen zu erstellen, deren Planung und Ausführung ziemlich mühsam sein wird. Im Allgemeinen ist es besser, PostgreSQL die Arbeit hier machen zu lassen. Im Allgemeinen habe ich Aktualisierungen in Zehntausenden von Zeilen in der von Ihnen beschriebenen Weise gefunden, um eine angemessene Leistung zu erzielen, aber es gibt eine wichtige Sache, die Sie vermeiden sollten.
Der Weg, dies zu tun, besteht darin, eine Auswahl und eine Verknüpfung in Ihrem Löschvorgang zu verwenden.
Unter keinen Umständen sollten Sie mit einer großen Tabelle wie folgt verfahren:
Dies führt normalerweise zu einem Antijoin in einer verschachtelten Schleife, was die Leistung ziemlich problematisch macht. Wenn Sie am Ende diesen Weg gehen müssen, tun Sie dies stattdessen:
PostgreSQL ist normalerweise ziemlich gut darin, schlechte Pläne zu vermeiden, aber es gibt immer noch Fälle, in denen es um äußere Verknüpfungen geht, die einen großen Unterschied zwischen guten und schlechten Plänen machen können.
Dies wandert ein wenig weiter, aber ich denke, es ist erwähnenswert, da es einfach ist, von IN nach NOT IN zu wechseln und den Performance-Tank für Abfragen zu beobachten.
quelle
IN ( select id from foo except select id from rows_to_keep )
Siehe postgresql.org/docs/9.4/static/queries-union.htmlIch bin auf diese Frage gestoßen, weil ich ein ähnliches Problem hatte. Ich bereinige eine Datenbank mit mehr als 300 Millionen Zeilen. Die endgültige Datenbank enthält nur etwa 30% der ursprünglichen Daten. Wenn Sie mit einem ähnlichen Szenario konfrontiert sind, ist es tatsächlich einfacher, eine neue Tabelle einzufügen und neu zu indizieren, als sie zu löschen.
Mach sowas wie
Mit der richtigen Indizierung von foo und bar können Sie Seq-Scans vermeiden.
Dann müssten Sie die Tabelle neu indizieren und umbenennen.
quelle