På grund av PostgreSQL MVCC, en UPDATE
är faktiskt ungefär som en DELETE
plus en INSERT
. Med det anmärkningsvärda undantaget av rostade värden - se:
- Skriver Postgres om hela raden vid uppdatering?
(Och mindre skillnader för enbart heap-tupler - DELETE
+ INSERT
startar en ny HOT-kedja - men det har ingen betydelse för det aktuella fallet.)
För att vara exakt är den "borttagna" raden helt enkelt osynlig för alla transaktioner som börjar efter att raderingen har begåtts, och dammsugs senare. Därför, på databassidan, inklusive indexmanipulering, finns det faktiskt ingen skillnad mellan de två uttalandena. (Undantag gäller, fortsätt läsa.) Det ökar nätverkstrafiken lite (beroende på dina data) och kräver lite analys.
Jag studerade HOT uppdateringar lite mer efter @araqnids input och körde några tester. Uppdateringar av kolumner som inte faktiskt ändrar värdet gör ingen skillnad vad som helst vad gäller HETA uppdateringar. Mitt svar håller. Se detaljer nedan.
Detta gäller även för rostade attribut, eftersom de inte heller berörs om inte värdena faktiskt ändras .
Men , om du använder utlösare per kolumn (introducerat med sid 9.0), detta kan ha oönskade biverkningar!
Jag citerar manualen om triggers:
... ett kommando som
UPDATE ... SET x = x ...
kommer att aktivera en utlösare på kolumnenx
, även om kolumnens värde inte ändrades .
Djärv betoning min.
Abstraktionsskikt är för bekvämlighet. De är användbara för SQL-analfabeter eller om applikationen behöver vara portabel mellan olika RDBMS. På nackdelen kan de slakta prestanda och introducera ytterligare felpunkter. Jag undviker dem när det är möjligt.
HETA (Heap-only tuple) uppdateringar
Heap-Only Tuples introducerades med Postgres 8.3, med viktiga förbättringar i 8.3.4 och 8.4.9.
Utgivningsinformationen för Postgres 8.3:
UPDATE
s ochDELETE
s lämnar döda tuplar efter sig, liksom misslyckadeINSERT
s. Tidigare endastVACUUM
kunde återta utrymme som tagits av döda tuplar. WithHOT dött tuppelutrymme kan återtas automatiskt vid tidpunkten förINSERT
ellerUPDATE
om inga ändringar görs i indexerade kolumner . Detta möjliggör mer konsekvent prestanda. Dessutom undviker HOT att lägga till dubbla indexposter.
Betoning min. Och "inga ändringar" inkluderar fall där kolumner uppdateras med samma värde som de redan har. Jag testade faktiskt , eftersom jag inte var säker.
I slutändan bekräftar den omfattande README.HOT i källkoden det.
Rostade kolumner står inte heller i vägen för HETA uppdateringar. Den HOT-uppdaterade tuppeln länkar bara till samma, oförändrade tuppel(er) i relationens toastgaffel. HETA uppdateringar fungerar till och med med rostade värden i mållistan (faktiskt ändrade eller inte). Om rostade värden ändras, medför det naturligtvis skrivningar till toastrelationens gaffel. Jag testade allt det också.
Ta inte mitt ord för det, se själv. Postgres tillhandahåller ett par funktioner för att kontrollera statistik. Kör din UPDATE
med och utan alla kolumner och kontrollera om det gör någon skillnad.
-- 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)
Eller använd pgAdmin. Välj din tabell och granska fliken "Statistik" i huvudfönstret.
Var medveten om att HOT-uppdateringar endast är möjliga när det finns plats för den nya tupelversionen på samma sida i huvudrelationsgaffeln. Ett enkelt sätt att tvinga fram det villkoret är att testa med en liten tabell som bara rymmer några få rader. Sidstorleken är vanligtvis 8k, så det måste finnas ledigt utrymme på sidan.