Em uma palestra re:Invent de 2015, a AWS mencionou que o vácuo deve ser executado não apenas após atualizações ou exclusões, mas também após inserções. Aqui está a parte relevante da palestra:
http://www.youtube.com/watch?v=tZXp19q8RFo&t=16m2s
Supostamente, há alguma limpeza que deve ser feita nos blocos, mesmo que eles tenham recebido apenas inserções e essa limpeza pode ser feita na primeira vez que um bloco é selecionado (diminuindo a leitura) ou durante o vácuo. Isso é verdade e, em caso afirmativo, exatamente qual limpeza deve ser feita?
tl;dr: O primeiro processo que lê os dados depois que eles são confirmados definirá os bits de dica. Isso sujará a página, criando atividade de gravação. A outra coisa
VACUUM
(mas não outros comandos) faz é marcar a página como totalmente visível, se apropriado.VACUUM
eventualmente terá que bater na mesa para congelar as tuplas.O trabalho que precisa ser feito após uma inserção não é realmente uma limpeza, pelo menos não no sentido de outro trabalho
VACUUM
normalmente feito. Antes de entrar em detalhes, observe que esta resposta é baseada no código 9.6 atual (não lançado) e estou ignorando os efeitos da replicação de streaming, mesmo que isso possa afetar a visibilidade.Por causa do MVCC , toda vez que o Postgres avalia se uma tupla deve ser visível para uma consulta, ele deve considerar se a transação que criou a tupla (registrada no campo oculto xmin) foi confirmada, juntamente com algum outro critério. Essa verificação é cara, portanto, assim que se sabe que uma transação está visível para todas as transações abertas no momento, um "bit de dica" é definido no cabeçalho da tupla indicando isso. A configuração desse bit suja a página, o que significa que terá que ser gravada no disco. Isso pode ser muito confuso se o próximo comando para ler os dados for um
SELECT
que de repente está criando muito tráfego de gravação. Executar umVACUUM
após os commits de inserção evitará isso. Outra distinção importante é queVACUUM
SEMPRE sugerirá tuplas em uma página (desde que tenha o bloqueio de limpeza na página), mas a maioria dos outros comandos apenas sugerirá se a transação de inserção for confirmada antes do início do comando.Um ponto importante sobre como escrever todos esses bits de dica é que eles
VACUUM
podem ser limitados (e o vácuo automático é limitado por padrão). Outros comandos não são limitados e gerarão dados sujos o mais rápido possível.VACUUM
é o único método para marcar páginas como totalmente visíveis, o que é uma importante consideração de desempenho para algumas operações (principalmente, varreduras somente de índice). Se você fizer uma inserção grande, é muito provável que haja muitas páginas com nada além de tuplas recém-inserida.VACUUM
pode potencialmente marcar essas páginas como totalmente visíveis, mas apenas se a transação em execução mais antiga quandoVACUUM
iniciada for mais recente que a transação que inseriu os dados .Devido ao funcionamento do MVCC, as tuplas que foram inseridas há mais de ~2 bilhões de transações devem ser marcadas como " congeladas ". Por padrão, o autovacuum entrará em ação para fazer isso a cada 200 milhões de transações. Executar um vácuo manual com vacuum_freeze_min_age definido como 0 após uma inserção em massa pode ajudar a reduzir o impacto disso. Mais agressivamente, você pode correr
VACUUM FREEZE
na mesa após a inserção. Isso iria "reiniciar o relógio" quando a próxima varredura congelada aconteceria.Se você quiser saber os detalhes específicos, dê uma olhada no
HEAPTUPLE_LIVE
caso após a chamada paraHeapTupleSatisfiesVacuum()
dentrolazy_scan_heap()
. Veja tambémHeapTupleSatisfiesVacuum()
a si mesmo e compare-o comHeapTupleSatisfiesMVCC()
.Há duas outras apresentações minhas que podem ser interessantes. O primeiro vídeo está disponível em http://www.pgcon.org/2015/schedule/events/829.en.html , enquanto o segundo (que acho um pouco melhor) em https://www.youtube. com/watch?v=L8nErzxPJjQ