A causa di PostgreSQL MVCC, un UPDATE
è effettivamente molto simile a un DELETE
più un INSERT
. Con la notevole eccezione dei valori tostati - vedi:
- Postgres riscrive l'intera riga durante l'aggiornamento?
(E differenze minori per le tuple solo heap - DELETE
+ INSERT
avvia una nuova catena HOT, ma ciò non ha alcun effetto sul caso in questione.)
Per essere precisi, la riga "eliminata" è semplicemente invisibile a qualsiasi transazione che inizia dopo che l'eliminazione è stata confermata e successivamente è stata svuotata. Pertanto, dal lato del database, inclusa la manipolazione dell'indice, non vi è in effetti nessuna differenza tra le due affermazioni. (Si applicano eccezioni, continua a leggere.) Aumenta un po' il traffico di rete (a seconda dei tuoi dati) e richiede un po' di analisi.
Ho studiato ancora gli aggiornamenti HOT dopo l'input di @araqnid ed ho eseguito alcuni test. Gli aggiornamenti sulle colonne che in realtà non modificano il valore non fanno differenza qualsiasi cosa per quanto riguarda gli aggiornamenti HOT. La mia risposta vale. Vedi i dettagli di seguito.
Questo vale anche per gli attributi tostati, poiché anche quelli non vengono toccati a meno che i valori non cambino effettivamente .
Tuttavia , se utilizzi attivatori per colonna (introdotto con pg 9.0), questo potrebbe avere effetti collaterali indesiderati!
Cito il manuale sui trigger:
... un comando come UPDATE ... SET x = x ...
attiverà un trigger sulla colonna x
, anche se il valore della colonna non è cambiato .
Enfasi in grassetto la mia.
I livelli di astrazione sono per comodità. Sono utili per sviluppatori SQL analfabeti o se l'applicazione deve essere portabile tra diversi RDBMS. Sul lato negativo, possono macellare le prestazioni e introdurre ulteriori punti di errore. Li evito ove possibile.
Aggiornamenti HOT (tupla solo heap)
Le tuple solo heap sono state introdotte con Postgres 8.3, con importanti miglioramenti in 8.3.4 e 8.4.9.
Le note di rilascio per Postgres 8.3:
UPDATE
se DELETE
s lascia tuple morte dietro, così come INSERT
fallito s.In precedenza solo VACUUM
potrebbe recuperare lo spazio occupato dalle tuple morte. Con HOT lo spazio della tupla inattiva può essere recuperato automaticamente al momento di INSERT
o UPDATE
se non vengono apportate modifiche alle colonne indicizzate . Ciò consente prestazioni più coerenti. Inoltre, HOT evita di aggiungere voci di indice duplicate.
Enfasi mia. E "nessuna modifica" include i casi in cui le colonne vengono aggiornate con lo stesso valore che già contengono. Ho veramente testato , poiché non ne ero sicuro.
In definitiva, l'ampio README.HOT nel codice sorgente lo conferma.
Anche le colonne tostate non ostacolano gli aggiornamenti HOT. La tupla aggiornata a HOT si collega semplicemente alle stesse tuple invariate nel fork di brindisi della relazione. Gli aggiornamenti HOT funzionano anche con i valori tostati nell'elenco di destinazione (effettivamente modificati o meno). Se i valori toast vengono modificati, ciò comporta ovviamente le scritture nel fork della relazione toast. Ho testato tutto anche questo.
Non credermi sulla parola, guarda tu stesso. Postgres fornisce un paio di funzioni per controllare le statistiche. Esegui il tuo UPDATE
con e senza tutte le colonne e controlla se fa la differenza.
-- 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)
Oppure usa pgAdmin. Seleziona la tua tabella e controlla la scheda "Statistiche" nella finestra principale.
Tieni presente che gli aggiornamenti HOT sono possibili solo quando c'è spazio per la nuova versione della tupla nella stessa pagina del fork della relazione principale. Un modo semplice per forzare tale condizione è eseguire il test con una piccola tabella che contiene solo poche righe. La dimensione della pagina è in genere 8k, quindi deve esserci spazio libero sulla pagina.