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. VACUUM
mü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 VACUUM
normalerweise 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 VACUUM
nach dem Einfügen ein Commit ausführen, wird dies vermieden. Ein weiterer wichtiger Unterschied ist dasVACUUM
wird 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 VACUUM
sie 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.
VACUUM
Dies 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. VACUUM
Diese Seiten können möglicherweise als "Alle sichtbar" markiert werden, jedoch nur, wenn die älteste ausgeführte Transaktion beim VACUUM
Start 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 FREEZE
nach 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_LIVE
Fall 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
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 dasCOMMIT
oder gesetzt werden, oderROLLBACK
?