PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Langsame einfache Aktualisierungsabfrage in einer PostgreSQL-Datenbank mit 3 Millionen Zeilen

Ich muss Tabellen mit 1 oder 2 Milliarden Zeilen mit verschiedenen Werten für jede Zeile aktualisieren. Jeder Lauf macht ~100 Millionen Änderungen (10%). Mein erster Versuch war, sie in Transaktionen von 300.000 Aktualisierungen direkt auf einer bestimmten Partition zu gruppieren, da Postgresql vorbereitete Abfragen nicht immer optimiert, wenn Sie Partitionen verwenden.

  1. Transaktionen von Haufen von "UPDATE myTable SET myField=value WHEREmyId=id"
    Ergibt 1.500 Aktualisierungen/Sek. was bedeutet, dass jeder Durchlauf mindestens 18 Stunden dauern würde.
  2. HOT aktualisiert die Lösung wie hier beschrieben mit FILLFACTOR=50. Ergibt 1.600 Updates/Sek. Ich verwende SSDs, also ist es eine kostspielige Verbesserung, da es die Speichergröße verdoppelt.
  3. Fügen Sie eine temporäre Tabelle mit aktualisierten Werten ein und führen Sie sie danach mit UPDATE...FROM zusammen. Ergibt 18.000 Aktualisierungen/Sek. wenn ich für jede Partition ein VACUUM mache; 100.000 U/s sonst. Cooool.
    Hier ist dieser Arbeitsablauf:
CREATE TEMP TABLE tempTable (id BIGINT NOT NULL, field(s) to be updated,
CONSTRAINT tempTable_pkey PRIMARY KEY (id));

Akkumulieren Sie eine Reihe von Aktualisierungen in einem Puffer, abhängig vom verfügbaren RAM, wenn er gefüllt ist oder die Tabelle/Partition geändert werden muss oder abgeschlossen ist:

COPY tempTable FROM buffer;
UPDATE myTable a SET field(s)=value(s) FROM tempTable b WHERE a.id=b.id;
COMMIT;
TRUNCATE TABLE tempTable;
VACUUM FULL ANALYZE myTable;

Das bedeutet, dass ein Durchlauf jetzt 1,5 Stunden statt 18 Stunden für 100 Millionen Updates dauert, Vakuum inbegriffen. Um Zeit zu sparen, ist es nicht notwendig, am Ende ein VOLLSTÄNDIGES Vakuum zu erstellen, aber selbst ein schnelles regelmäßiges Vakuumieren ist nützlich, um Ihre Transaktions-ID in der Datenbank zu kontrollieren und während der Stoßzeiten kein unerwünschtes automatisches Vakuum zu erhalten.