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

Ein Überblick über die VACUUM-Verarbeitung in PostgreSQL

PostgreSQL verwendet keinen IN-PLACE-Aktualisierungsmechanismus, also gemäß der Art und Weise, wie die Befehle DELETE und UPDATE entworfen wurden,

  • Wann immer DELETE-Operationen ausgeführt werden, markiert es das vorhandene Tupel als DEAD, anstatt diese Tupel physisch zu entfernen.
  • In ähnlicher Weise markiert es jedes Mal, wenn eine UPDATE-Operation ausgeführt wird, das entsprechende vorhandene Tupel als DEAD und fügt ein neues Tupel ein (d. h. UPDATE-Operation =DELETE + INSERT).

Also führt jeder DELETE- und UPDATE-Befehl zu einem DEAD-Tupel, das niemals verwendet wird (es sei denn, es gibt parallele Transaktionen). Diese toten Tupel führen zu einer unnötigen zusätzlichen Speicherplatznutzung, obwohl die gleiche oder eine geringere Anzahl effektiver Datensätze vorhanden ist. Dies wird in PostgreSQL auch als Space Bloating bezeichnet. Da PostgreSQL weithin als OLTP-artiges relationales Datenbanksystem verwendet wird, in dem häufig INSERT-, UPDATE- und DELETE-Operationen ausgeführt werden, gibt es viele DEAD-Tupel und damit entsprechende Konsequenzen. PostgreSQL benötigte also einen starken Wartungsmechanismus, um mit diesen DEAD-Tupeln umzugehen. VACUUM ist der Wartungsprozess, der sich um den Umgang mit dem DEAD-Tupel kümmert, zusammen mit einigen weiteren Aktivitäten, die für die Optimierung des VACUUM-Betriebs nützlich sind. Lassen Sie uns einige Begriffe verstehen, die später in diesem Blog verwendet werden.

Sichtbarkeitskarte

Wie der Name schon sagt, verwaltet es Sichtbarkeitsinformationen über Seiten, die nur Tupel enthalten, von denen bekannt ist, dass sie für alle aktiven Transaktionen sichtbar sind. Für jede Seite wird ein Bit verwendet. Wenn das Bit auf 1 gesetzt ist, sind alle Tupel der entsprechenden Seite sichtbar. Das auf 0 gesetzte Bit bedeutet, dass auf der angegebenen Seite kein freier Speicherplatz vorhanden ist und Tupel für alle Transaktionen sichtbar sein können.

Die Sichtbarkeitskarte wird für jede Relation (Tabelle und Index) verwaltet und neben den Hauptrelationen zugeordnet, d. h. wenn der Knotenname der Relationendatei 12345 ist, dann wird die Sichtbarkeitsdatei in der Paralleldatei 12345_vm gespeichert.

Freiraumkarte

Es verwaltet Informationen zum freien Speicherplatz, die Details über den verfügbaren Speicherplatz in der Relation enthalten. Dies wird auch in der Datei parallel zur Hauptdatei der Beziehung gespeichert, d. h. wenn der Knotenname der Beziehungsdatei 12345 ist, dann wird die Kartendatei des freien Speicherplatzes in der parallelen Datei 12345_fsm gespeichert.

Tupel einfrieren

PostgreSQL verwendet 4 Bytes zum Speichern der Transaktions-ID, was bedeutet, dass maximal 2 Milliarden Transaktionen generiert werden können, bevor es umläuft. Stellen Sie sich nun vor, dass zu diesem Zeitpunkt noch ein Tupel die anfängliche Transaktions-ID enthält, sagen wir 100, dann sagen wir für die neue Transaktion (die die Wrap-Around-Transaktion verwendet) 5, die Transaktions-ID 100 wird in die Zukunft schauen und es wird nicht möglich sein, die hinzugefügten Daten zu sehen /geändert, obwohl es eigentlich in der Vergangenheit war. Um diese spezielle Transaktions-ID zu vermeiden, wird FrozenTransactionId (gleich 2) zugewiesen. Diese spezielle Transaktions-ID wird immer als in der Vergangenheit liegend betrachtet und ist für alle Transaktionen sichtbar.

VAKUUM

Die Hauptaufgabe von VACUUM besteht darin, Speicherplatz zurückzugewinnen, der von DEAD-Tupeln belegt ist. Zurückgeforderter Speicherplatz wird nicht an das Betriebssystem zurückgegeben, sondern nur innerhalb derselben Seite defragmentiert, sodass sie nur für die Wiederverwendung durch zukünftige Dateneinfügungen in dieselbe Tabelle verfügbar sind. Während die VACUUM-Operation für eine bestimmte Tabelle ausgeführt wird, können gleichzeitig andere READ/WRITE-Operationen für dieselbe Tabelle ausgeführt werden, da keine exklusive Sperre für die bestimmte Tabelle verwendet wird. Falls kein Tabellenname angegeben ist, wird VACUUM für alle Tabellen der Datenbank ausgeführt. Die VACUUM-Operation führt eine Reihe von Operationen innerhalb einer ShareUpdateExclusive-Sperre aus:

  • Alle Seiten aller Tabellen (oder angegebenen Tabellen) der Datenbank scannen, um alle toten Tupel zu erhalten.
  • Bei Bedarf alte Tupel einfrieren.
  • Entferne das Index-Tupel, das auf die entsprechenden DEAD-Tupel zeigt.
  • Entfernen Sie die DEAD-Tupel einer Seite, die einer bestimmten Tabelle entsprechen, und weisen Sie die Live-Tupel auf der Seite neu zu.
  • Aktualisieren Sie die Karte des freien Speicherplatzes (FSM) und die Sichtbarkeitskarte (VM).
  • Schneiden Sie die letzte Seite wenn möglich ab (falls es DEAD-Tupel gab, die freigegeben wurden).
  • Alle entsprechenden Systemtabellen aktualisieren.

Wie wir aus den obigen Arbeitsschritten für VACUUM ersehen können, ist es klar, dass es sich um eine sehr kostspielige Operation handelt, da alle Seiten der Relation verarbeitet werden müssen. Daher ist es sehr wichtig, mögliche Seiten zu überspringen, die nicht gesaugt werden müssen. Da die Sichtbarkeitskarte (VM) Auskunft darüber gibt, auf welcher Seite kein freier Speicherplatz vorhanden ist, kann davon ausgegangen werden, dass das entsprechende Seitenvakuum nicht erforderlich ist und diese Seite daher sicher übersprungen werden kann.

Da VACUUM ohnehin alle Seiten und alle ihre Tupel durchläuft, nutzt es die Gelegenheit, um andere wichtige Aufgaben zu erledigen, nämlich die qualifizierenden Tupel einzufrieren.

Volles VAKUUM

Wie im vorherigen Abschnitt besprochen, hilft VACUUM, obwohl es alle DEAD-Tupel entfernt und die Seite für die zukünftige Verwendung defragmentiert, nicht dabei, den Gesamtspeicher der Tabelle zu reduzieren, da tatsächlich kein Platz für die freigegeben wird Betriebssystem. Angenommen, eine Tabelle tbl1, in der der Gesamtspeicher 1,5 GB erreicht hat und von diesem 1 GB durch ein totes Tupel belegt ist, dann stehen nach VACUUM weitere ungefähr 1 GB für weitere Tupeleinfügungen zur Verfügung, aber der Gesamtspeicher bleibt weiterhin bei 1,5 GB.

Full VACUUM löst dieses Problem, indem tatsächlich Speicherplatz freigegeben und an das Betriebssystem zurückgegeben wird. Aber das hat seinen Preis. Im Gegensatz zu VACUUM erlaubt FULL VACUUM keinen parallelen Betrieb, da es eine exklusive Sperre für die Beziehung nimmt, die VOLL VACUUMiert wird. Unten sind die Schritte:

  • Sperrt exklusiv die Relation.
  • Erstellen Sie eine parallele leere Speicherdatei.
  • Kopiert alle Live-Tupel aus dem aktuellen Speicher in den neu zugewiesenen Speicher.
  • Geben Sie dann den ursprünglichen Speicher frei.
  • Freigabe der Sperre.

So wie es auch aus den Schritten ersichtlich ist, wird nur der Speicherplatz für die verbleibenden Daten benötigt.

Automatisches VAKUUM

Anstatt VACUUM manuell auszuführen, unterstützt PostgreSQL einen Dämon, der VACUUM regelmäßig automatisch auslöst. Jedes Mal, wenn VACUUM aufwacht (standardmäßig 1 Minute), ruft es mehrere Werke auf (je nach Konfiguration autovacuum_worker-Prozesse).

Auto-Vakuum-Worker führen gleichzeitig VACUUM-Prozesse für die jeweiligen designierten Tabellen durch. Da VACUUM keine exklusive Sperre auf Tabellen nimmt, wirkt es sich nicht (oder nur minimal) auf andere Datenbankarbeiten aus.

Die Konfiguration von Auto-VACUUM sollte basierend auf dem Nutzungsmuster der Datenbank erfolgen. Es sollte nicht zu häufig sein (da es das Aufwachen der Worker verschwendet, da es möglicherweise keine oder zu wenige tote Tupel gibt) oder zu lange verzögert (es wird viele tote Tupel zusammen und somit eine Tabellenaufblähung verursachen).

VAKUUM oder Voll-VAKUUM

Idealerweise sollte die Datenbankanwendung so gestaltet sein, dass das VOLLSTÄNDIGE VAKUUM nicht benötigt wird. Wie oben erläutert, erstellt FULL VACUUM Speicherplatz neu und legt die Daten zurück. Wenn also nur weniger tote Tupel vorhanden sind, wird sofort Speicherplatz neu erstellt, um alle ursprünglichen Daten zurückzulegen. Da FULL VACUUM außerdem die Tabelle exklusiv sperrt, blockiert es alle Operationen auf der entsprechenden Tabelle. Daher kann das VOLLSTÄNDIGE VAKUUM manchmal die gesamte Datenbank verlangsamen.

Zusammenfassend Full VACUUM sollte vermieden werden, es sei denn, es ist bekannt, dass der Großteil des Speicherplatzes auf tote Tupel zurückzuführen ist. Die PostgreSQL-Erweiterung pg_freespacemap kann verwendet werden, um einen guten Hinweis auf freien Speicherplatz zu erhalten.

Sehen wir uns ein Beispiel für den erklärten VAKUUM-Prozess an.

Als Erstes erstellen wir eine Tabelle demo1:

postgres=# create table demo1(id int, id2 int);

CREATE TABLE

Und fügen Sie dort einige Daten ein:

postgres=# insert into demo1 values(generate_series(1,10000), generate_series(1,

10000));

INSERT 0 10000

postgres=# SELECT count(*) as npages, round(100 * avg(avail)/8192 ,2) as average_freespace_ratio FROM pg_freespace('demo1');

 npages | average_freespace_ratio

--------+-------------------------

  45 |                0.00

(1 row)

Jetzt löschen wir Daten:

postgres=# delete from demo1 where id%2=0;

DELETE 5000

Und führen Sie ein manuelles Vakuum durch:

postgres=# vacuum demo1;

VACUUM

postgres=# SELECT count(*) as npages, round(100 * avg(avail)/8192 ,2) as average_freespace_ratio FROM pg_freespace('demo1');

 npages | average_freespace_ratio

--------+-------------------------

  45 |               45.07

(1 row)

Dieser freie Speicherplatz steht jetzt zur Wiederverwendung durch PostgreSQL zur Verfügung, aber wenn Sie diesen Speicherplatz für das Betriebssystem freigeben möchten, führen Sie Folgendes aus:

postgres=# vacuum full demo1;

VACUUM

postgres=# SELECT count(*) as npages, round(100 * avg(avail)/8192 ,2) as average_freespace_ratio FROM pg_freespace('demo1');

 npages | average_freespace_ratio

--------+-------------------------

  23 |                0.00

(1 row)

Schlussfolgerung

Und dies war ein kurzes Beispiel dafür, wie der VAKUUM-Prozess funktioniert. Glücklicherweise müssen Sie sich dank des automatischen Vakuumprozesses die meiste Zeit und in einer gewöhnlichen PostgreSQL-Umgebung darüber keine Gedanken machen, da dies von der Engine selbst verwaltet wird.