Quanto tempo leva uma operação de vácuo / vácuo automático?

18

Gerencio um grande banco de dados (algumas centenas de shows) contendo tabelas com várias funções, algumas delas com milhões de registros. Algumas tabelas recebem apenas um grande número de inserções e exclusões, outras poucas inserções e grande número de atualizações.

O banco de dados é executado no PostgreSQL 8.4 em um sistema Debian 6.0 amd64 com 16 gigabytes de RAM.

A questão é, às vezes, o processo de autovacuum em uma tabela, que leva muito tempo (dias) para ser concluído. Quero poder dizer quanto tempo um determinado comando a vácuo levará para poder decidir se o cancelo ou não. Além disso, se houvesse um indicador de progresso para as operações de vácuo do postgres, seria realmente útil.

Editar:

Não estou procurando uma solução à prova de balas. Apenas uma dica aproximada sobre o número de tuplas mortas ou bytes de E / S necessários é suficiente para decidir. É realmente irritante não ter idéia de quando VACUUMvai terminar, qualquer que seja.

Eu vi que pg_catalog.pg_stat_all_tablestem uma coluna para o número de tuplas mortas. Portanto, é possível ter uma estimativa, mesmo que isso signifique que a pessoa tenha que estar ANALYZEna tabela antes. Por outro lado, autovacuum_vacuum_thresholde autovacuum_vacuum_scale_factoras configurações sozinho provar que postgres si sabe algo sobre a quantidade de mudança nas mesas e provavelmente coloca nas mãos do DBA também.

Não tenho certeza de qual consulta executar, porque quando executo VACUUM VERBOSE, vejo que não apenas as tabelas, mas os índices nelas também estão sendo processados.

zaadeh
fonte

Respostas:

34

No meu PostgreSQL (8.3) eu uso este truque:

  1. Eu recebo o tamanho do disco da tabela usando pg_total_relation_size()- isso inclui índices e tamanho do TOAST, que é o que VACUUMprocessa. Isso me dá a idéia de quantos bytes ele VACUUMprecisa ler.
  2. Eu corro VACUUMem cima da mesa.
  3. Acho pido VACUUMprocesso (em pg_catalog.pg_stat_activity).
  4. No shell do Linux, eu corro while true; do cat /proc/123/io | grep read_bytes; sleep 60; done(onde 123está o pid) - isso me mostra os bytes lidos pelo processo a partir do disco até agora.

Isso me dá uma idéia aproximada de quantos bytes são processados ​​(lidos) a cada minuto pelo VACUUM. Presumo que o VACUUMdeve ler toda a tabela (incluindo índices e TOAST), cujo tamanho de disco eu conheço na etapa 1.

Presumo que a tabela seja grande o suficiente para que a maioria das páginas seja lida no disco (elas não estão presentes na memória compartilhada do Postgres), portanto o read_bytescampo é bom o suficiente para ser usado como um contador de progresso.

Sempre que eu fazia isso, o total de bytes lidos pelo processo não excedia 5% do tamanho total da relação, então acho que essa abordagem pode ser boa o suficiente para você.

Roman Hocke
fonte
Nasty :) Isso também funciona para versões posteriores? E, mais importante, para autovacuum?
Dezso
Eu não tentei para versões mais recentes. Ele deve funcionar para VACUUM FULL9.0+, pois reescreve completamente a tabela. Também deve funcionar regularmente VACUUM, mas ainda não o testei. Pois autovacuumfuncionaria se você fosse capaz de capturar o processo de trabalho de autovacuum em uma determinada tabela, mas não sei como conseguir isso.
Roman Hocke 6/03/2017
Você tem alguma sugestão de como conseguir isso com o RDS? Naturalmente, não temos acesso a um shell linux ao usar o RDS, mas gostaríamos muito de poder estimar isso também.
Jwg2s
@ jwg2s O que você quer dizer com "RDS", por favor? Serviços de banco de dados da Amazon? Se assim for, eu sou, infelizmente, não familiarizado com ele :-( Talvez o seu apoio ajudaria.
Roman Hocke
1
Parece funcionar bem no PG 10 com o vácuo cheio também.
DylanYoung
9

Isso é muito difícil de determinar. Você pode ajustar o vácuo automático para ser mais agressivo ou mais suave. Mas quando definido como moderado e está atrasado e a carga básica de E / S é muito alta, pode acontecer que ele nunca atinja um estado de vácuo adequado - então você vê o processo em execução e executando e executando. Além disso, edições posteriores do PostreSQL têm recursos aprimorados de autovacuum, isso por si só pode ser suficiente para mudar para um deles (de preferência 9.2 como o mais recente).

A barra de progresso parece uma boa ideia, mas imagino que não seja tão fácil de implementar de maneira significativa. Como você tem carga constante em suas tabelas, é bem possível que o progresso esteja aparentemente voltando para trás (quero dizer que a contagem de linhas mortas / porcentagem aumenta em vez de diminuir) - então que conclusão você tira?

dezso
fonte
2
Prefiro ver algum tipo de indicador de progresso, mesmo que retroceda, em vez de nada.
zaadeh
3
VACUUM ANALYZE VERBOSEpelo menos imprime alguma atividade no console, como faz. É melhor do que apenas olhar para um prompt estático, perguntando se algo está parado por horas.
Nome falso
A pergunta é sobre "vácuo / vácuo automático". O exposto acima é útil apenas para VACUUM, não para o vácuo automático, mas ainda é algo.
Fake Name
@FakeName Eh, eu interpretei mal a pergunta - perdi a parte do vácuo manual. Desculpe, estou excluindo meu comentário.
Dezso
3

Em nossa produção, uma das maiores tabelas tinha esse log:

pages: 0 removed, 1801722 remain
tuples: 238912 removed, 42582083 remain, 1396 are dead but not yet removable
buffer usage: 9477565 hits, 3834218 misses, 2220101 dirtied
avg read rate: 2.976 MB/s, avg write rate: 1.723 MB/s
system usage: CPU 68.47s/177.49u sec elapsed 10065.08 sec

Esse é de longe o pior consumo de recursos, todas as outras tabelas levaram menos de 2 s.

Para ver esses tipos de logs, você deve executar isto:

alter system set log_autovacuum_min_duration TO 5; 

(por 5 ms), recarregue o arquivo de configuração.

stonelazy
fonte
3

Achei este post e este post úteis, mas, como outros mencionaram, pode ser difícil calcular o progresso geral do vácuo, uma vez que o processo envolve algumas operações separadas.

Eu uso essa consulta para monitorar o progresso da verificação da tabela do vácuo, que parece ser a maior parte do trabalho:

SELECT heap_blks_scanned/cast(heap_blks_total as numeric)*100 as heap_blks_percent, progress.*, activity.query
FROM pg_stat_progress_vacuum AS progress
INNER JOIN pg_stat_activity AS activity ON activity.pid = progress.pid;

No entanto, isso não inclui a verificação de índice, que acontece depois e pode levar tanto tempo, se não mais, se você tiver uma tonelada de índices. Infelizmente, não consigo encontrar uma maneira de monitorar a varredura / aspiração de índice.

Cerin
fonte