Lohnt es sich, VACUUM für eine Tabelle auszuführen, die nur INSERTs empfängt?

19

In einem Vortrag zu re: Invent 2015 erwähnte AWS, dass Vakuum nicht nur nach Aktualisierungen oder Löschungen, sondern auch nach Einfügungen ausgeführt werden sollte. Hier ist der relevante Teil des Vortrags:

http://www.youtube.com/watch?v=tZXp19q8RFo&t=16m2s

Angeblich müssen einige Blöcke bereinigt werden, auch wenn sie nur Einfügungen erhalten haben. Diese Bereinigung kann entweder beim ersten Auswählen eines Blocks (Verlangsamung des Lesevorgangs) oder während des Vakuums durchgeführt werden. Ist das wahr und wenn ja, was genau muss aufgeräumt werden?

foobar0100
quelle

Antworten:

15

tl; dr: Der erste Prozess, der Daten liest, nachdem sie festgeschrieben wurden, setzt Hinweisbits. Dadurch wird die Seite verschmutzt und Schreibaktivität erzeugt. Die andere Möglichkeit VACUUM(aber keine anderen Befehle) besteht darin, die Seite gegebenenfalls als sichtbar zu markieren. VACUUMmüssen schließlich den Tisch treffen, um die Tupel einzufrieren.

Die Arbeit, die nach einer Einfügung ausgeführt werden muss, ist nicht wirklich bereinigend, zumindest nicht im Sinne der anderen Arbeit, die VACUUMnormalerweise ausgeführt wird. Beachten Sie, dass diese Antwort auf dem aktuellen (unveröffentlichten) 9.6-Code basiert und die Auswirkungen der Streaming-Replikation ignoriert werden, obwohl sie sich auf die Sichtbarkeit auswirken können.

Aufgrund von MVCC muss Postgres bei jeder Bewertung, ob ein Tupel für eine Abfrage sichtbar sein soll, berücksichtigen, ob die Transaktion, die das Tupel erstellt hat (im ausgeblendeten Feld xmin aufgezeichnet), zusammen mit einigen anderen Kriterien festgeschrieben wurde. Diese Prüfung ist teuer. Sobald bekannt ist, dass eine Transaktion für alle derzeit geöffneten Transaktionen sichtbar ist, wird im Tupel-Header ein "Hinweisbit" gesetzt, das dies anzeigt. Die Einstellung dieses Bits verschmutzt die Seite, was bedeutet, dass es auf die Festplatte geschrieben werden muss. Dies kann sehr verwirrend sein, wenn der nächste Befehl zum Lesen der Daten ein Befehl ist SELECT, der plötzlich viel Schreibverkehr erzeugt. Wenn Sie VACUUMnach dem Einfügen ein Commit ausführen, wird dies vermieden. Ein weiterer wichtiger Unterschied ist dasVACUUMwird IMMER Tupel auf einer Seite andeuten (solange die Bereinigungssperre auf der Seite aktiviert ist), aber die meisten anderen Befehle werden nur andeuten, wenn die Einfügetransaktion festgeschrieben wurde, bevor der Befehl gestartet wurde.

Ein wichtiger Punkt beim Schreiben all dieser Hinweisbits ist, dass VACUUMsie gedrosselt werden können (und das automatische Vakuum ist standardmäßig gedrosselt). Andere Befehle werden nicht gedrosselt und erzeugen so schnell wie möglich fehlerhafte Daten.

VACUUMDies ist die einzige Methode zum Markieren von Seiten als "Alle sichtbar". Dies ist ein wichtiger Leistungsaspekt für einige Vorgänge (insbesondere nur Indexscans). Wenn Sie eine große Einfügung machen, ist es sehr wahrscheinlich, dass es viele Seiten mit nur neu eingefügten Tupeln gibt. VACUUMDiese Seiten können möglicherweise als "Alle sichtbar" markiert werden, jedoch nur, wenn die älteste ausgeführte Transaktion beim VACUUMStart neuer war als die Transaktion, mit der die Daten eingefügt wurden .

Weil, wie MVCC arbeitet, Tupel , die mehr eingesetzt wurden als ~ 2 Milliarden Transaktionen vor müssen als „gekennzeichnet werden eingefroren “. Standardmäßig wird bei jeder 200-Millionen-Transaktion automatisch Vakuum aktiviert. Das Ausführen eines manuellen Vakuums, bei dem vacuum_freeze_min_age auf 0 gesetzt ist, nachdem ein Bulk-Insert erstellt wurde, kann dazu beitragen, die Auswirkungen zu verringern. Aggressiver könnte man VACUUM FREEZEnach dem Einfügen auf dem Tisch laufen . Das würde "die Uhr zurücksetzen", wenn der nächste Freeze-Scan stattfinden würde.

Wenn Sie die spezifischen Details kennen möchten, werfen Sie einen Blick auf den HEAPTUPLE_LIVEFall nach dem Anruf nach HeapTupleSatisfiesVacuum()innen lazy_scan_heap(). Siehe auch HeapTupleSatisfiesVacuum()selbst und vergleiche es mit HeapTupleSatisfiesMVCC().

Es gibt zwei andere Präsentationen von mir, die interessant sein könnten. Das erste Video ist unter http://www.pgcon.org/2015/schedule/events/829.en.html verfügbar , während das zweite (was meiner Meinung nach etwas besser war) unter https://www.youtube zu finden ist. com / watch? v = L8nErzxPJjQ

Jim Nasby
quelle
Dies ist sehr interessant und erklärt auch einige unsaubere Seiten in bestimmten EXPLAIN (ANALYZE, BUFFERS) outputs. But, if I understand things correctly, some of the hint bits (at least * COMMITTED` und *INVALID) können (könnten) schon durch das COMMIToder gesetzt werden, oder ROLLBACK?
25.
3
COMMIT und ROLLBACK nicht wirklich Datenseiten berühren, also nein, diese Befehle speziell könnte nie andeuten. Ein DML-Befehl kann weiterhin sowohl den xmin- als auch den xmax-Hinweisstatus festlegen, entweder für Tupel, die von anderen Transaktionen markiert wurden, oder möglicherweise sogar für Tupel, die von der aktuellen Transaktion markiert wurden.
Jim Nasby