Por que o VACUUM ANALYZE não limpa todas as tuplas mortas?


8

Executamos um "manual" VACUUM ANALYZE VERBOSEem algumas de nossas tabelas maiores depois de fazer grandes DELETE/INSERTalterações nelas. Isso parece funcionar sem problemas, embora às vezes o VACUUMtrabalho de uma tabela seja executado por horas (consulte esta postagem para obter problemas e raciocínios semelhantes).

Ao fazer mais pesquisas, descobri que temos tabelas grandes com um grande número de tuplas mortas, mesmo após a execução VACUUM. Por exemplo, aqui estão algumas das estatísticas produzidas a partir da consulta nesta resposta .

-[ RECORD 50 ]--+---------------------------
relname         | example_a
last_vacuum     | 2014-09-23 01:43
last_autovacuum | 2014-08-01 01:19
n_tup           |    199,169,568
dead_tup        |    111,048,906
av_threshold    |     39,833,964
expect_av       | *
-[ RECORD 51 ]--+---------------------------
relname         | example_b
last_vacuum     | 2014-09-23 01:48
last_autovacuum | 2014-08-30 12:40
n_tup           |    216,596,624
dead_tup        |    117,224,220
av_threshold    |     43,319,375
expect_av       | *
-[ RECORD 52 ]--+---------------------------
relname         | example_c
last_vacuum     | 2014-09-23 01:55
last_autovacuum | 2014-09-23 18:25
n_tup           |    309,831,136
dead_tup        |    125,047,233
av_threshold    |     61,966,277
expect_av       | *

O último campo afirma que essas (e a maioria das tabelas) atingiriam o limite para o vácuo automático. No entanto, tendo acabado de executar VACUUM ANALYZE VEBOSEem cada uma dessas tabelas, a contagem de tupla morta não deve ser 0 (ou próximo de 0, não 125M de 300M)?

A documentação declara:

O VACUUM recupera o armazenamento ocupado por tuplas mortas.

Isso significa que o nosso VACUUMnão está funcionando?


ATUALIZAR

Por solicitação em repsonse, aqui estão alguns logs dos VERBOSEtrabalhos:

INFO:  vacuuming "public.example_1"
INFO:  scanned index "idx_example_1_on_gp_id_and_dd_id" to remove 378386 row versions
DETAIL:  CPU 1.83s/3.42u sec elapsed 23.01 sec.
INFO:  scanned index "index_example_1_on_q_id" to remove 378386 row versions
DETAIL:  CPU 2.10s/3.91u sec elapsed 18.92 sec.
INFO:  "example_1": removed 378386 row versions in 7085 pages
DETAIL:  CPU 0.09s/0.05u sec elapsed 0.19 sec.
INFO:  index "idx_example_1_on_gp_id_and_dd_id" now contains 30347438 row versions in 291065 pages
DETAIL:  378386 index row versions were removed.
165587 index pages have been deleted, 164287 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  index "index_example_1_on_q_id" now contains 30347438 row versions in 333287 pages
DETAIL:  378386 index row versions were removed.
152773 index pages have been deleted, 152757 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "example_1": found 1773 removable, 401984 nonremovable row versions in 14438 out of 1493006 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 10567 unused item pointers.
0 pages are entirely empty.
CPU 4.26s/7.51u sec elapsed 46.10 sec.
INFO:  vacuuming "pg_toast.pg_toast_17917"
INFO:  index "pg_toast_17917_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "pg_toast_17917": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_1"
INFO:  "example_1": scanned 30000 of 1493006 pages, containing 611502 live rows and 0 dead rows; 30000 rows in sample, 40563141 estimated total rows

Esta tabela agora mostra 0 tuplas mortas nas estatísticas. A maioria das tabelas tem tuplas mortas muito mais baixas hoje de manhã, portanto o nosso VACUUMou o vácuo automático está funcionando.

Temos algumas tabelas que não produzem nada e ainda mostram tuplas mortas:

-[ RECORD 49 ]--+---------------------------
relname         | example_2
last_vacuum     | 2014-09-23 02:23
last_autovacuum | 2014-09-02 14:30
n_tup           |    117,914,944
dead_tup        |     34,507,388
av_threshold    |     23,583,039
expect_av       | *

Algumas vezes eu vi nos logs onde os índices serão verificados repetidamente. Isso parece corresponder a trabalhos de longa duração VACUUM. Alguma idéia do porquê? Isso é apenas uma solução para o bloqueio de registros (não acho que alguma gravação estivesse ocorrendo durante a execução desses trabalhos).

INFO:  vacuuming "public.example_2"
...
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2795959 row versions
DETAIL:  CPU 3.88s/16.54u sec elapsed 23.09 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2795959 row versions
DETAIL:  CPU 6.74s/21.13u sec elapsed 84.64 sec.
INFO:  "example_2": removed 2795959 row versions in 48214 pages
DETAIL:  CPU 0.71s/0.32u sec elapsed 33.65 sec.
INFO:  scanned index "index_example_2_on_gsg_id_and_dd_id" to remove 2591011 row versions
DETAIL:  CPU 2.84s/16.11u sec elapsed 19.28 sec.
INFO:  scanned index "index_example_2_on_q_id" to remove 2591011 row versions
DETAIL:  CPU 5.46s/22.70u sec elapsed 130.57 sec.
INFO:  "example_2": removed 2591011 row versions in 45539 pages
DETAIL:  CPU 0.67s/0.38u sec elapsed 15.16 sec.
INFO:  index "index_example_2_on_gsg_id_and_dd_id" now contains 123807784 row versions in 1560915 pages
DETAIL:  108836958 index row versions were removed.
1100790 index pages have been deleted, 718471 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.25 sec.
INFO:  index "index_example_2_on_q_id" now contains 123807784 row versions in 1886087 pages
DETAIL:  110336259 index row versions were removed.
1058063 index pages have been deleted, 266983 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.07 sec.
INFO:  "example_2": found 124808 removable, 1355901 nonremovable row versions in 2086343 out of 6966379 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 7858495 unused item pointers.
0 pages are entirely empty.
CPU 595.49s/2130.13u sec elapsed 5656.34 sec.
INFO:  vacuuming "pg_toast.pg_toast_18079"
INFO:  index "pg_toast_18079_index" now contains 0 row versions in 1 pages
DETAIL:  0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  "pg_toast_18079": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL:  0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
INFO:  analyzing "public.example_2"
INFO:  "example_2": scanned 30000 of 6966379 pages, containing 528443 live rows and 522 dead rows; 30000 rows in sample, 152953760 estimated total rows

0 dead row versions cannot be removed yet.indica que você não possui transações de longa execução que bloqueariam a remoção de tuplas mortas.
Erwin Brandstetter

Respostas:


10

O VACUUM só pode remover tuplas mortas mortas há muito tempo, ou seja, mortas para todos os usos possíveis. Se você possui transações de longa duração, elas podem impedir a remoção das tuplas recentemente mortas.

Este é um exemplo de uma situação em que uma transação de longa duração impediu a remoção:

INFO:  "pgbench_accounts": found 0 removable, 2999042 nonremovable row versions in 49181 out of 163935 pages
DETAIL:  2999000 dead row versions cannot be removed yet.

Na verdade, não são transações de longa duração, mas instantâneos de longa duração. Certamente, uma instrução select ou insert de longa duração fará isso. Para níveis de isolamento mais altos que o confirmado pela leitura, a transação inteira manterá o instantâneo até que fique inoperante; portanto, se alguns abrirem uma transação de leitura repetível e, em seguida, sair de férias sem confirmar, isso seria um problema. As transações preparadas com suspensão também serão realizadas (se você não souber o que é uma transação preparada, provavelmente não as usará).

Os exemplos que você mostra não indicam um problema, mas você também diz que o problema havia sido resolvido até então. Se este for um problema recorrente, você provavelmente deve começar a registrar a saída de suas instruções VACUUM VERBOSE, para poder encontrar as informações que cobrem o período durante o qual o problema existe.

As várias passagens sobre o índice são devidas às suas configurações maintenance_work_mem. Ele pode remover apenas uma tupla para cada 6 bytes de memória em cada passagem no índice e precisa fazer várias passagens se você precisar remover mais do que isso. Portanto, aumentar o maintenance_work_mem ajudará.


Você pode fornecer um exemplo do que podem ser "transações de longa duração"? Você quer dizer uma consulta ou INSERT/ IMPORT? Ou você quer dizer algo mais do que uma conexão abrir / fechar?
precisa saber é o seguinte

4

O tamanho da tabela física normalmente (exceto a remoção oportunista de páginas removíveis do final da tabela) não é reduzido pela execução VACUUM(ou VACUUM ANALYZE). Você precisa correr VACUUM FULLpara encolher a mesa.

Esta é uma citação da resposta relacionada, que possui mais detalhes:

Por documentação (apenas algumas linhas abaixo da sua cotação):

A planície VACUUM(sem FULL) simplesmente recupera o espaço e o disponibiliza para reutilização. Essa forma de comando pode operar em paralelo com a leitura e gravação normais da tabela, pois não é obtido um bloqueio exclusivo. No entanto, o espaço extra não é retornado ao sistema operacional (na maioria dos casos);

Mais aqui:

Você estará interessado em pg_repack , que pode fazer o mesmo que VACUUM FULLsem bloqueios exclusivos.


11
Desculpe se minha pergunta não estava clara, mas eu estava perguntando sobre as tuplas mortas restantes. Eu sei que VACUUMsem FULLnão vai reduzir o tamanho do disco, e eu estou bem com isso. Mencionei uma tabela grande por causa do post que vinculei à primeira afirmando que uma estratégia de vácuo agressiva ajustada seria uma "vitória ... se houver tabelas grandes cujas linhas nunca sejam excluídas nem atualizadas". Nossas mesas grandes são trocadas diariamente.
precisa saber é o seguinte
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.