No início da manhã, todos os dias, um trabalho do pgAgent atualiza o conteúdo da tabela A da tabela B no meu banco de dados PostgreSQL 8.4. A Tabela A contém cerca de 140k registros em 91 colunas e possui dois índices - um como parte da PRIMARY KEY e o outro um índice GIST em uma coluna de geometria do POINT PostGIS.
Para acelerar o processo, o trabalho solta o índice na coluna de geometria, antes de excluir os registros na tabela A e inserir os registros da tabela B, o índice é recriado. Isso tudo sendo feito, o daemon de autovacuum começa a funcionar quando lhe apetecer (depois de dez minutos aproximadamente, comparando as estatísticas da tarefa e as estatísticas da tabela para o tempo de conclusão da tarefa e o tempo de execução do autovacuum).
Ao verificar a mesa esta manhã, depois que tudo isso aconteceu, as estatísticas da tabela me disseram que o tamanho da tabela era 272MB, o tamanho da tabela TOAST era 8192bytes e o tamanho do índice era 23MB. Isso parecia muito grande, então eu emiti um comando REINDEX na tabela e o tamanho do índice caiu para 9832kB.
Minha (s) pergunta (s) é esta:
Por que o REINDEX aparentemente reduz tanto o tamanho dos índices quando os índices (ou pelo menos o índice da coluna geométrica) foram criados novamente do zero? Devo garantir que a tabela tenha sido aspirada / analisada antes da criação dos índices? A queda do índice na chave primária não é um fator disso? o que estou perdendo?
fonte
ANALYZE
o tamanho relatado também diminui.Respostas:
Se a instrução CREATE INDEX perceber que outra sessão contém uma captura instantânea ativa que ainda pode estar interessada nos registros excluídos, ela incluirá esses registros excluídos no novo índice.
Da mesma forma, se um REINDEX perceber que outra sessão possui uma captura instantânea ativa que ainda possa estar interessada nos registros excluídos, ele incluirá esses registros excluídos no novo índice.
Se um VACUUM perceber que outra sessão possui uma captura instantânea ativa que ainda pode estar interessada nos registros excluídos, ele os manterá na tabela. E o REINDEX ou CREATE INDEX também precisará carregá-los para o novo índice, desde que o instantâneo ainda exista.
Quando houver ou não houver mais instantâneos que possam ver as linhas excluídas, o VACUUM poderá removê-las da tabela. Mas um CREATE INDEX ou REINDEX também não poderia transportá-los para o novo índice, independentemente de o VACUUM ter conseguido removê-los da capacidade ou não.
Portanto, no seu cenário, a função do VACUUM entre o CREATE INDEX inicial e o REINDEX provavelmente é apenas para ocupar um tempo, período durante o qual sua transação de longa duração provavelmente desaparece por conta própria e descarta o instantâneo interferente.
fonte
Tendo tentado diferentes ordens de execução, parece que executar um VACUUM antes de uma instrução REINDEX é a única maneira de obter a redução no tamanho, talvez porque o espaço não aspirado seja adicionado ao índice (indexação de registros excluídos?). Forçando a reescrita de uma tabela usando
faz o mesmo tipo de coisa, pois limpa o espaço fora de uso.
Ter que VACUUM no meio do processo interrompe o fluxo um pouco, pois é necessário emitir um comando VACUUM fora de uma transação.
fonte