sql >> Database >  >> RDS >> PostgreSQL

Redundante gegevens in update-statements

Vanwege PostgreSQL MVCC, een UPDATE lijkt in feite veel op een DELETE plus een INSERT . Met de opmerkelijke uitzondering van geroosterde waarden - zie:

  • Herschrijft Postgres de hele rij bij update?

(En kleine verschillen voor alleen heap-tupels - DELETE + INSERT begint een nieuwe HOT-keten - maar dat heeft geen invloed op de zaak in kwestie.)

Om precies te zijn, de "verwijderde" rij is gewoon onzichtbaar voor elke transactie die begint nadat de verwijdering is gepleegd en later wordt opgezogen. Daarom is er aan de databasekant, inclusief indexmanipulatie, in feite geen verschil tussen de twee uitspraken. (Uitzonderingen zijn van toepassing, lees verder.) Het verhoogt het netwerkverkeer een beetje (afhankelijk van uw gegevens) en moet een beetje worden geparseerd.

Ik heb HOT-updates nog wat bestudeerd na de input van @araqnid en heb wat tests uitgevoerd. Updates voor kolommen die de waarde niet echt veranderen, maken geen verschil wat dan ook wat betreft HOT updates. Mijn antwoord houdt stand. Zie details hieronder.

Dit geldt ook voor getoaste attributen, aangezien deze ook niet worden aangeraakt tenzij de waarden feitelijk veranderen .

Echter , als u triggers per kolom . gebruikt (geïntroduceerd met pg 9.0), dit kan ongewenste bijwerkingen hebben!

Ik citeer de handleiding over triggers:

... een commando zoals UPDATE ... SET x = x ... zal een trigger activeren op kolom x , ook al is de waarde van de kolom niet veranderd .

Vetgedrukte nadruk van mij.

Abstractielagen zijn voor het gemak. Ze zijn handig voor ontwikkelaars die analfabeet zijn met SQL of als de applicatie overdraagbaar moet zijn tussen verschillende RDBMS. Aan de andere kant kunnen ze de prestaties verbeteren en extra faalpunten introduceren. Ik vermijd ze waar mogelijk.

HOT (Heap-only tuple) updates

Heap-Only Tuples werden geïntroduceerd met Postgres 8.3, met belangrijke verbeteringen in 8.3.4 en 8.4.9.
De release-opmerkingen voor Postgres 8.3:

UPDATE s en DELETE s laat dode tuples achter, net als mislukte INSERT s.Voorheen alleen VACUUM ruimte kon terugwinnen die ingenomen werd door dode tupels. WithHOT kan dode tuple-ruimte automatisch worden teruggevorderd op het moment van INSERT of UPDATE als er geen wijzigingen zijn aangebracht in geïndexeerde kolommen . Dit zorgt voor meer consistente prestaties. HOT vermijdt ook het toevoegen van dubbele indexvermeldingen.

Benadruk de mijne. En "geen wijzigingen" omvat gevallen waarin kolommen worden bijgewerkt met dezelfde waarde als ze al bevatten. Ik eigenlijk getest , omdat ik het niet zeker wist.

Uiteindelijk bevestigt de uitgebreide README.HOT in de broncode het.

Geroosterde kolommen staan ​​ook HOT-updates niet in de weg. De HOT-bijgewerkte tuple linkt gewoon naar dezelfde, ongewijzigde tuple(s) in de toastvork van de relatie. HOT-updates werken zelfs met getoaste waarden in de doellijst (feitelijk gewijzigd of niet). Als de getoaste waarden worden gewijzigd, brengt dit uiteraard schrijfacties met zich mee naar de toast-relatievork. Ik heb dat ook allemaal getest.

Geloof me niet op mijn woord, kijk zelf maar. Postgres biedt een aantal functies om statistieken te controleren. Voer uw UPDATE uit met en zonder alle kolommen en controleer of het enig verschil maakt.

-- 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)

Of gebruik pgAdmin. Selecteer uw tafel en inspecteer het tabblad "Statistieken" in het hoofdvenster.

Houd er rekening mee dat HOT-updates alleen mogelijk zijn als er ruimte is voor de nieuwe tuple-versie op dezelfde pagina van de hoofdrelatievork. Een eenvoudige manier om die voorwaarde te forceren, is door te testen met een kleine tabel die slechts een paar rijen bevat. Het paginaformaat is doorgaans 8k, dus er moet vrije ruimte op de pagina zijn.



  1. Hoe een IF-statement in SQL uit te voeren?

  2. SELECT COUNT(*) AS count - Hoe deze telling te gebruiken

  3. Geef tabel door als parameter in sql-server UDF

  4. Inleiding tot SQL-opdrachten