Postgresql unterscheidet sich von anderen DBMS darin, dass während des UPDATE-Vorgangs keine Änderungen an der vorhandenen Zeile vorgenommen werden. Stattdessen wird eine Kopie der Zeile erstellt, die sich vom Original von den Werten der Spalten unterscheidet, die von der Aktualisierung betroffen sind. Sie sind im Original alt und werden in der Kopie geändert. Auf diese Weise können Sie einerseits das Blockieren bei der Ausführung von Lese- und Schreibanforderungen vermeiden und andererseits alte Versionen von Zeilen, die niemand jemals lesen wird, ständig bereinigen. In Verbindung mit dieser architektonischen Besonderheit stellt sich häufig die Frage, was passiert, wenn Sie etwas wie den Zeitpunkt des letzten Zugriffs auf Daten in der Datenbank speichern müssen, der sich ansonsten nicht ändert. Wird es auf die Leistung reagieren? Wird es zu einer ständigen Umstrukturierung der Indizes kommen?
Kurz gesagt, ja, Copy On Write funktioniert nirgendwo, aber in vielen Fällen können Indizes dank HOT nicht neu erstellt werden.
Heap only-Tupel, auch als HOT bezeichnet, sind die Optimierung, die Postgres verwendet, um die für Aktualisierungen erforderliche E / A-Menge zu reduzieren. Aufgrund von MVCC besteht ein Update in Postgres darin, eine Zeile für das Update zu finden und neue Versionen der Zeile in die Datenbank einzufügen. Der Hauptnachteil dieses Verfahrens ist die Notwendigkeit, jedem Index eine neue Zeile hinzuzufügen.
Dies erfordert viel mehr E / A, da die Zeile erneut in jeden Index in der Tabelle eingefügt werden muss. Das erneute Einfügen ist erforderlich, da sich die physische Position der neuen Version einer Zeile auf der Festplatte von der physischen Position der alten Version unterscheidet.
Um die für UPDATE erforderliche E / A-Menge zu reduzieren, fügte das Postgres-Team Postgres HOT hinzu. Die Idee hinter HOT ist relativ einfach. Wenn möglich, erstellt Postgres beim Aktualisieren der Linie eine neue Kopie der Linie unmittelbar nach der alten Kopie der Linie. Außerdem ist in der alten Kopie der Zeichenfolge ein spezielles Etikett angebracht, damit Postgres weiß, dass die neue Kopie der Zeichenfolge unmittelbar nach der alten liegt. Daher ist es nicht erforderlich, alle Indizes zu aktualisieren.
Während des Index-Scans, für den eine neue Kopie des Strings übergeben wird, findet der Postgres-Filter die alte Kopie des Strings. Da sich auf der alten Kopie der Linie ein spezielles Etikett befindet, wird Postgres verstehen, dass sich die neue Kopie der Linie unmittelbar nach der alten befindet, die neue Version findet und diese verwendet. Es stellt sich heraus, dass sich Postgres in solchen Fällen so verhalten kann, als ob alle Indizes auf eine neue Kopie des Strings verweisen, und dass sie nicht neu erstellt werden müssen.
Jetzt ist HOT nur beteiligt, wenn nur nicht indizierbare Spalten an der Aktualisierung beteiligt sind. Wenn mindestens eine an der Aktualisierung beteiligte Spalte im Index enthalten ist, kann HOT nicht angewendet werden. In diesem Fall gibt es mehrere Probleme bei der Verwendung von HOT. Wenn beispielsweise der Index für die zu aktualisierende Spalte durch einen Scan indiziert wird und die alte Kopie der Zeile in das Prädikat des Scans fällt, die neue jedoch nicht. In diesem Fall versucht Postgres, mithilfe des Index schnell alle Zeilen zu finden, die für das Abfrageprädikat geeignet sind. Bei Spalten, die mit HOT aktualisiert wurden, wird eine neue Kopie der Zeile erstellt, die nicht mit dem Abfrageprädikat übereinstimmt. Aufgrund dieser Einschränkung (dass HOT nicht funktioniert, wenn indizierbare Spalten im Update enthalten sind) kann Postgres garantieren, dass bei der Suche nach Zeilen, die für das Prädikat geeignet sind, durch das der Index geleitet wird, die neue Version der Zeile gefunden wird, wenn das Prädikat mit der alten Version der Zeile übereinstimmt passt auch zu ihm und umgekehrt.
Derzeit wird eine HOT-Erweiterung namens WARM entwickelt, die auch beim Aktualisieren von Spalten funktioniert, für die Indizes erstellt werden. Die Idee hinter WARM ist, unmittelbar nach der alten Zeile eine neue Zeile einzufügen und die Zeile für Indizes zu aktualisieren, bei denen die Spalten geändert wurden. Dies erschwert die beschriebene Situation erheblich, da Postgres jetzt irgendwie feststellen muss, ob die Zeile den Filter für den Index passiert oder nicht.
PS Im ursprünglichen Artikel wird der HOT-Mechanismus beschrieben, aber hier haben wir den Mechanismus im Auge, bei dem es sich nur um Tupel handelt, und der Begriff selbst hat eine separate Bedeutung.
Heap only tuple ist nur eine neue Version der Zeile. So seltsam es auch scheinen mag, ein Heap ist eine Tabelle, und Heap bedeutet nur, dass diese Zeile nur von der Kette gefunden werden kann, die von der älteren Version der Zeile namens root ausgeht.