tl; dr: il primo processo che legge i dati dopo il commit imposta bit di suggerimento. Ciò sporcherà la pagina, creando attività di scrittura. L'altra cosa VACUUM
(ma non altri comandi) è contrassegnare la pagina come tutto visibile, se appropriato. VACUUM
alla fine dovrà colpire il tavolo per congelare le tuple.
Il lavoro che deve essere fatto dopo un inserto non è realmente pulito, almeno non nel senso dell'altro lavoro VACUUM
normalmente. Prima di entrare nei dettagli, nota che questa risposta si basa sul codice 9.6 (inedito) corrente e sto ignorando gli effetti della replica in streaming, anche se può influire sulla visibilità.
A causa di MVCC , ogni volta che Postgres valuta se una tupla deve essere visibile a una query, deve considerare se la transazione che ha creato la tupla (registrata nel campo nascosto xmin) ha eseguito il commit, insieme ad alcuni altri criteri. Tale controllo è costoso, quindi non appena è noto che una transazione è visibile a tutte le transazioni attualmente aperte, nell'intestazione della tupla viene impostato un "bit di suggerimento". L'impostazione di quel bit sporca la pagina, il che significa che dovrà essere scritta su disco. Questo può essere molto confuso se il prossimo comando per leggere i dati è un SELECT
che sta improvvisamente creando molto traffico di scrittura. Eseguire un VACUUM
dopo l'inserimento dell'inserimento lo eviterà. Un'altra importante distinzione è quellaVACUUM
suggerirà SEMPRE le tuple su una pagina (purché abbia il blocco di pulizia sulla pagina), ma la maggior parte degli altri comandi suggerirà solo se la transazione di inserimento è stata impegnata prima dell'avvio del comando.
Un punto importante sulla scrittura di tutti questi bit di suggerimento è che VACUUM
può essere limitato (e l'autovacuum è limitato per impostazione predefinita). Altri comandi non sono limitati e genereranno dati sporchi il più rapidamente possibile.
VACUUM
è l'unico metodo per contrassegnare le pagine come completamente visibili, che è una considerazione importante delle prestazioni per alcune operazioni (in particolare, le scansioni solo dell'indice). Se si esegue un inserto di grandi dimensioni, è molto probabile che ci siano molte pagine con nient'altro che tuple appena inserite. VACUUM
può potenzialmente contrassegnare quelle pagine come completamente visibili, ma solo se la transazione in esecuzione più vecchia all'avvio VACUUM
era più recente della transazione che ha inserito i dati .
A causa del funzionamento di MVCC, le tuple inserite più di ~ 2 miliardi di transazioni fa devono essere contrassegnate come " congelate ". Per impostazione predefinita, l'autovacuum prenderà il via per farlo ogni 200 milioni di transazioni. L'esecuzione di un vuoto manuale con vacuum_freeze_min_age impostato su 0 dopo un inserimento in blocco può contribuire a ridurne l'impatto. Più aggressivamente, potresti eseguire VACUUM FREEZE
sul tavolo dopo l'inserimento. Ciò "reimposterebbe l'orologio" quando si verifica la successiva scansione congelata.
Se vuoi conoscere i dettagli specifici, dai un'occhiata al HEAPTUPLE_LIVE
caso dopo la chiamata HeapTupleSatisfiesVacuum()
all'interno lazy_scan_heap()
. Vedi anche HeapTupleSatisfiesVacuum()
se stesso e confrontalo con HeapTupleSatisfiesMVCC()
.
Ci sono altre due mie presentazioni che potrebbero essere interessanti. Il primo video è disponibile da http://www.pgcon.org/2015/schedule/events/829.en.html , mentre il secondo (che penso fosse un po 'meglio) su https://www.youtube. com / watch? v = L8nErzxPJjQ
EXPLAIN (ANALYZE, BUFFERS) outputs. But, if I understand things correctly, some of the hint bits (at least
* COMMITTED` e*INVALID
) può (potrebbe) essere già impostato dalCOMMIT
oROLLBACK
, giusto?