Autovacuum ist seit langem Teil von PostgreSQL. Doch wie funktioniert das wirklich? Können Sie es einfach ein- und ausschalten? Die Leute stellen immer wieder diese Fragen zum Aktivieren und Deaktivieren des Autovakuums. PostgreSQL verlässt sich auf MVCC, um die Parallelität in einer Mehrbenutzerumgebung zu übergeben. Das Problem, das bei der Verarbeitung gleichzeitiger Transaktionen auftritt, ist, dass tote Tupel bereinigt werden müssen. In PostgreSQL wird dies durch den Befehl VACUUM behandelt. Das manuelle Ausführen von VACUUM gehört jedoch der Vergangenheit an. Die meisten Leute verlassen sich auf den PostgreSQL Autovacuum Daemon, um das Cleanup zu handlen.
So funktioniert Autovacuum
Das erste, was zu verstehen ist, ist, dass Autovacuum wirklich das tut, was es sagt: Im Grunde ist es Automatisierung rund um manuelles VAKUUM. Alles, was es tut, ist, für eine Weile zu schlafen und regelmäßig zu überprüfen, ob eine Tabelle verarbeitet werden muss. Es gibt drei Dinge, um die sich Autovacuum kümmert:
- Erstellen von Statistiken für den PostgreSQL-Optimierer (ANALYZE)
- Tote Reihen bereinigen
- Handhabung des Rundumschutzes
In PostgreSQL ist autovacuum ein serverseitiger Daemon, der immer vorhanden ist. Ja, das stimmt: IMMER. Selbst wenn Sie autovacuum in postgresql.conf deaktivieren (oder indem Sie ALTER SYSTEM verwenden, um postgresql.auto.conf anzupassen), wird der Daemon immer noch da sein – von Design – um den Wraparound-Schutz zu unterstützen.
Die Art und Weise, wie Autovacuum funktioniert, ist: Es überprüft regelmäßig, ob Arbeit erledigt werden muss, und benachrichtigt den Postmaster, falls neue Arbeiter gestartet werden müssen, um sich um einen Table zu kümmern. Autovacuum startet einen Arbeiter nicht direkt, sondern arbeitet direkt über den Postmaster, um sicherzustellen, dass alle Prozesse auf einer Ebene sind. Die Tatsache, dass es über den Postmaster funktioniert, trägt eindeutig dazu bei, das System zuverlässiger zu machen.
Lassen Sie uns einen genaueren Blick darauf werfen, was Autovacuum tut.
Autovacuum erstellt Optimiererstatistiken
Der PostgreSQL-Optimierer stützt sich stark auf Statistiken. Es schätzt die Anzahl der Zeilen, die von verschiedenen Vorgängen zurückgegeben werden, und versucht, den besten Weg zur Optimierung einer Abfrage zu erraten.
Dazu wird die statistische Verteilung der Daten in einer Tabelle verwendet. Für den Fall, dass sich der Inhalt einer Tabelle ändert, muss der Optimierer veraltete Daten verwenden, was wiederum zu einer schlechten Leistung führen kann.
Daher tritt das Autovakuum regelmäßig ein, um alle Statistiken zu aktualisieren. Autovacuum basiert auf verschiedenen Konfigurationsparametern (zu finden in postgresql.conf), die geändert werden können, um dieses Verhalten zu optimieren:
autovacuum_analyze_threshold = 50
# min Anzahl der Zeilenaktualisierungen vor der Analyse
autovacuum_analyze_scale_factor = 0.1
# Anteil der Tabellengröße vor der Analyse
Diese Parameter teilen dem Autovakuum mit, wann neue Statistiken erstellt werden sollen. Im obigen Fall lautet die Regel wie folgt:
Schwellenwert analysieren = Basisschwellenwert analysieren +
Skalierungsfaktor analysieren * Anzahl der Tupel
Angesichts der Standardkonfiguration leistet autovacuum in der Regel gute Arbeit, um Statistiken automatisch zu verwalten. Manchmal ist es jedoch notwendig, eine genauere Kontrolle auszuüben:
test=# CREATE TABLE t_foo (id int) WITH (autovacuum_analyze_scale_factor = 0.05);
CREATE TABLE
test=# \d+ t_foo
Table "public.t_foo"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
——–+———+———–+———-+———+———+————–+————-
id | integer | | | | plain | |
Access method: heap
Options: autovacuum_analyze_scale_factor=0.05
In diesem Beispiel habe ich autovacuum_analyze_scale_factor auf 0.05 eingestellt, um das Autovakuum aggressiver zu machen. Hin und wieder ist das notwendig – vor allem, wenn Tabellen sehr, sehr groß sind.
Autovakuum reinigt tote Rows
Das Erstellen neuer Optimierer Statistiken ist sehr wichtig. Es gibt jedoch noch mehr: Tote Rows zu säubern. Der Zweck von VACUUM im Allgemeinen besteht darin, sicherzustellen, dass tote Zeilen aus Heaps und Indizes entfernt werden.
Normalerweise sind die Standardeinstellungen in Ordnung. Genau wie im Fall von ANALYZE kann es jedoch sinnvoll sein, diese Parameter anzupassen, um den Autovacuum-Daemon entweder aggressiver zu machen oder sich entspannter zu verhalten.
Das Festlegen von Autovakuum Parametern kann entweder global erfolgen, wenn die Tabelle erstellt wird (siehe postgresql.conf oder postgresql.auto.conf), oder später im Prozess, wie in der nächsten Auflistung gezeigt:
test=# ALTER TABLE t_foo
SET (autovacuum_vacuum_scale_factor = 0.4);
ALTER TABLE
In diesem Fall haben wir den Skalierungsfaktor geändert und das Autovakuum seltener in Kraft treten lassen.
Autovacuum verarbeitet Transaktionsumbruch
Es gibt eine dritte Sache, die Autovacuum tut: Es verhindert Transaktionsumbruch.
Wraparound-Schutz ist eine wichtige Sache, die nicht auf die leichte Schulter genommen werden darf; Es kann zu schwerwiegenden Ausfallzeiten und Problemen bei verschiedenen Workloads führen.
Aktivieren und Deaktivieren des Autovakuums
Autovacuum kann global deaktiviert werden. Dies bedeutet jedoch NICHT, dass der Daemon gestoppt wird – es bedeutet lediglich, dass er NUR einen Wraparound-Schutz bietet. Der Grund, warum dies geschieht, ist sicherzustellen, dass Ausfallzeiten so weit wie möglich minimiert werden. Es ist einfacher, mit Tableblähungen zu leben als mit Ausfallzeiten.
Daher ist es nicht wirklich möglich, das Autovakuum zu stoppen – es kann nur für die meisten Aufgaben ausgesetzt werden. Es ist sowieso keine gute Idee, das Autovakuum komplett auszuschalten. In den meisten Fällen verursacht das Ausschalten nur Probleme.
Sinnvoll ist es, das Autovakuum in speziellen Szenarien auf einzelnen Tabellen zu übergehen. Hier ist ein Szenario, in dem es sinnvoll sein könnte:
- Eine Tabelle wird erstellt
- VIELE Daten werden in die Tabelle geladen
- Änderungen und Korrekturen werden vorgenommen (UPDATE, DELETE)
- Aggregationen werden durchgeführt und an einem anderen Ort gespeichert
- Die Tabelle wird sofort oder am nächsten Tag weggeworfen
Warum sollte sich in diesem Fall jemand um Wraparound, Cleanup und so weiter kümmern? Wenn klar ist, dass ein Table sowieso weggeworfen wird, warum sollte man ihn aufräumen? Denken Sie daran: Wir sprechen hier über sehr spezifische Szenarien, und wir sprechen definitiv nicht über Allzwecktabellen.
So können Sie das Autovakuum für einen einzelnen Table ein- und ausschalten:
test=# ALTER TABLE t_foo SET (autovacuum_enabled = off);
ALTER TABLE
test=# ALTER TABLE t_foo SET (autovacuum_enabled = on);
ALTER TABLE
Bitte haben Sie Verständnis dafür, dass das Ausschalten des Autovakuums sicherlich keine gute Idee ist, es sei denn, Sie stehen vor einem bestimmten Anwendungsfall mit einer starken Begründung dafür.
Manuelles VAKUUM vs. automatisches VAKUUM
Was passiert, wenn das Autovakuum läuft, aber jemand ein manuelles VACUUM startet? Generell gilt: Autovakuum verliert immer. Wenn Sie ein VACUUM starten, aber bereits ein Autovacuum-Worker ausgeführt wird, beendet PostgreSQL den Worker und gibt Ihrem Personalprozess Priorität.
Das Gleiche gilt für so ziemlich alle anderen Operationen. Angenommen, jemand möchte eine Spalte, eine Tabelle usw. löschen. Im Falle eines Konflikts wird PostgreSQL immer den Autovakuum-Prozess beenden und sicherstellen, dass normale Benutzervorgänge nicht durch Hintergrundoperationen beeinträchtigt werden.
Warum ist Autovakuum so langsam?
Viele Leute fragen sich immer wieder, warum Autovakuum langsamer ist als manuelles VACUUM. Zunächst einmal ist es in der Standardkonfiguration in der Tat wahr, dass Autovacuum viel langsamer ist als manuelles VACUUM. Der Grund ist eine Sache, die allgemein als Kostenverzögerung bekannt ist:
test=# SHOW autovacuum_vacuum_cost_delay;
autovacuum_vacuum_cost_delay
——————————
2ms
(1 row)
Wenn VACUUM auf einen Table trifft, geschieht dies normalerweise mit "voller Geschwindigkeit", was bedeutet, dass das Aufräumen eines Tables zu massiven E/A-Engpässen führen kann. Ein einzelner VACUUM-Auftrag kann Hunderte von Megabyte an E/A pro Sekunde saugen – was weniger Kapazität für andere Operationen lässt und wiederum zu schlechten Reaktionszeiten führen kann.
Die Lösung besteht darin, das Autovakuum für I/O zu bestrafen und dem Prozess zusätzliche Verzögerungen hinzuzufügen. Die Verarbeitung einer Tabelle dauert länger, führt jedoch zu geringeren Gesamtauswirkungen auf andere Prozesse. In älteren Versionen von PostgreSQL lag die Einstellung bei 20 Millisekunden. Es wurde jedoch in PostgreSQL 13 und darüber hinaus auf 2 Millisekunden reduziert.
Die künstlichen Verzögerungen (die pro Tabelle deaktiviert werden können) sind der Hauptgrund, warum Endbenutzer Laufzeitunterschiede beobachten.