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

Redundante Daten in Update-Anweisungen

Wegen PostgreSQL MVCC ein UPDATE ist praktisch wie ein DELETE plus ein INSERT . Mit der bemerkenswerten Ausnahme von gerösteten Werten - siehe:

  • Schreibt Postgres beim Update die gesamte Zeile neu?

(Und geringfügige Unterschiede für reine Heap-Tupel - DELETE + INSERT startet eine neue HOT-Kette - aber das hat nichts mit dem vorliegenden Fall zu tun.)

Um genau zu sein, die "gelöschte" Zeile ist für jede Transaktion, die nach dem Festschreiben des Löschvorgangs beginnt, einfach unsichtbar und wird später entfernt. Daher gibt es auf der Datenbankseite, einschließlich der Indexmanipulation, praktisch keinen Unterschied zwischen den beiden Aussagen. (Es gelten Ausnahmen, lesen Sie weiter.) Es erhöht den Netzwerkverkehr ein wenig (abhängig von Ihren Daten) und erfordert ein wenig Parsing.

Ich habe HOT-Updates nach @araqnids Input weiter studiert und einige Tests durchgeführt. Aktualisierungen von Spalten, die den Wert nicht wirklich ändern, machen keinen Unterschied was auch immer in Bezug auf HOT-Updates betrifft. Meine Antwort gilt. Einzelheiten siehe unten.

Dies gilt auch für geröstete Attribute, da diese ebenfalls nicht berührt werden, es sei denn, die Werte ändern sich tatsächlich .

Allerdings , wenn Sie Spalten-Trigger verwenden (eingeführt mit Seite 9.0), dies kann unerwünschte Nebenwirkungen haben!

Ich zitiere das Handbuch zu Triggern:

... ein Befehl wie UPDATE ... SET x = x ... löst einen Trigger auf Spalte x aus , obwohl sich der Wert der Spalte nicht geändert hat .

Fettdruck von mir.

Abstraktionsschichten dienen der Bequemlichkeit. Sie sind nützlich für Entwickler ohne SQL-Kenntnisse oder wenn die Anwendung zwischen verschiedenen RDBMS portierbar sein muss. Auf der anderen Seite können sie die Leistung beeinträchtigen und zusätzliche Fehlerquellen einführen. Ich vermeide sie wo immer möglich.

HOT (nur Heap-Tupel) Updates

Heap-Only-Tupel wurden mit Postgres 8.3 eingeführt, mit wichtigen Verbesserungen in 8.3.4 und 8.4.9.
Die Versionshinweise für Postgres 8.3:

UPDATE s und DELETE s hinterlassen tote Tupel, ebenso wie gescheitertes INSERT s.Bisher nur VACUUM könnte von toten Tupeln belegten Speicherplatz zurückgewinnen. WithHOT-Dead-Tuple-Speicherplatz kann zum Zeitpunkt von INSERT automatisch zurückgewonnen werden oder UPDATE wenn keine Änderungen an indizierten Spalten vorgenommen werden . Dies ermöglicht eine konsistentere Leistung. Außerdem vermeidet HOT das Hinzufügen doppelter Indexeinträge.

Betonung von mir. Und "keine Änderungen" schließt Fälle ein, in denen Spalten mit demselben Wert aktualisiert werden, den sie bereits enthalten. Ich habe eigentlich getestet , da ich mir nicht sicher war.

Letztendlich bestätigt es die umfangreiche README.HOT im Quellcode.

Geröstete Spalten stehen auch HOT-Updates nicht im Weg. Das HOT-aktualisierte Tupel verlinkt einfach auf dasselbe, unveränderte Tupel in der Toastgabelung der Relation. HOT-Updates funktionieren sogar mit gerösteten Werten in der Zielliste (tatsächlich geändert oder nicht). Wenn getoastete Werte geändert werden, führt dies offensichtlich zu Schreibvorgängen in den Toast-Relation-Fork. Ich habe das alles auch getestet.

Nehmen Sie mich nicht beim Wort, überzeugen Sie sich selbst. Postgres bietet einige Funktionen zum Überprüfen von Statistiken. Führen Sie Ihr UPDATE aus mit und ohne alle Spalten und prüfen Sie, ob es einen Unterschied macht.

-- Number of rows HOT-updated in table:
SELECT pg_stat_get_tuples_hot_updated('table_name'::regclass::oid)

-- Number of rows HOT-updated in table, in the current transaction:
SELECT pg_stat_get_xact_tuples_hot_updated('table_name'::regclass::oid)

Oder verwenden Sie pgAdmin. Wählen Sie Ihren Tisch aus und überprüfen Sie die Registerkarte "Statistiken" im Hauptfenster.

Beachten Sie, dass HOT-Updates nur möglich sind, wenn Platz für die neue Tupelversion auf derselben Seite der Hauptbeziehungsgabel vorhanden ist. Eine einfache Möglichkeit, diese Bedingung zu erzwingen, besteht darin, mit einer kleinen Tabelle zu testen, die nur wenige Zeilen enthält. Die Seitengröße beträgt normalerweise 8 KB, daher muss auf der Seite freier Speicherplatz vorhanden sein.