Preciso executar o VACUUM FULL sem espaço em disco disponível

27

Eu tenho uma tabela que ocupa quase 90% do espaço em hd no nosso servidor. Decidi soltar algumas colunas para liberar espaço. Mas preciso retornar o espaço para o sistema operacional. O problema, porém, é que não tenho certeza do que acontecerá se eu executar o VACUUM FULL e não houver espaço livre suficiente para fazer uma cópia da tabela.

Entendo que o VACUUM FULL não deve ser usado, mas achei que era a melhor opção nesse cenário.

Todas as idéias seriam apreciadas.

Estou usando o PostgreSQL 9.0.6

Justin
fonte

Respostas:

19

Como você não tem espaço suficiente para executar um vácuo ou reconstruir, sempre é possível reconstruir seus bancos de dados postgresql restaurando-os. A restauração de bancos de dados, tabelas e índices liberará espaço e desfragmentação. Posteriormente, você pode configurar a manutenção automatizada para limpar seus bancos de dados regularmente.

1 Faça backup de todos os bancos de dados em seu servidor postgresql

Você deseja fazer backup de todos os seus bancos de dados em uma partição que tenha espaço suficiente. Se você estava no Linux, pode usar o gzip para compactar ainda mais o backup e economizar espaço

su - postgres
pg_dumpall | gzip -9 > /some/partition/all.dbs.out.gz

2 Faça backup dos seus arquivos de configuração

cp /path/to/postgresql/data_directory/*.conf /some/partition/

3 Pare o Postgresql

pg_ctl -D /path/to/postgresql/data_directory stop

4 apague o conteúdo do diretório de dados

rm -Rf /path/to/postgresql/data_directory/*

5 Execute initdb para reinitalizar seu diretório de dados

initdb -D /path/to/postgresql/data_directory

6 Restaurar arquivos de configuração

cp /some/partition/*.conf /path/to/postgresql/data_directory/*.conf 

7 Inicie o Postgresql

pg_ctl -D /path/to/postgresql/data_directory start

8 Restaure o despejo de todos os bancos de dados criados

gunzip /some/partition/all.dbs.out.gz
psql -f /some/partition/all.dbs.out
Craig Efrein
fonte
11
Obrigado, foi isso que acabei fazendo, com algumas diferenças. Acabei de soltar o banco de dados depois de fazer o backup. Em seguida, criou um novo e o restaurou.
30712 Justin
De nada. Imaginei que remover o conteúdo do diretório de dados e executar o initdb seria suficiente.
Craig Efrein
Worked great, I just recommend skipping the gzip part to save time.
Rafael Barbosa
17

NOTA: Eu testei isso na 9.1. Não tenho nenhum servidor 9.0 por aqui. Tenho muita certeza de que ele funcionará no 9.0.


CUIDADO (Conforme observado nos comentários de @erny):

Note that high CPU load due to I/O operations may be expected.

Você pode fazer isso praticamente sem tempo de inatividade usando um espaço de tabela temporário. O tempo de inatividade será na forma de bloqueios exclusivos. Mas apenas na mesa você está aspirando. Então, tudo o que acontecerá é que as consultas do cliente simplesmente aguardarão a aquisição do bloqueio se eles acessarem a tabela em questão. Você não precisa fechar as conexões existentes.

Uma coisa a ter em mente, porém, é que mover a mesa e o vácuo cheio precisará esperar primeiro um bloqueio exclusivo!


Primeiro, você obviamente precisa de algum armazenamento adicional. Como Stéphanemencionado nos comentários, isso precisa ser pelo menos duas vezes maior que a tabela em questão, VACUUM FULLassim como uma cópia completa. Se você tiver sorte e puder adicionar dinamicamente um disco à máquina, faça isso. Na pior das hipóteses , você pode simplesmente conectar um disco USB (embora seja arriscado e lento)!

Em seguida, monte o novo dispositivo e disponibilize-o como espaço de tabela:

CREATE TABLESPACE tempspace LOCATION '/path/to/new/folder';

Você pode listar os espaços de tabela facilmente usando:

\db

Verifique duas vezes o espaço de tabela atual da sua tabela (você precisa saber para onde movê-lo de volta):

SELECT tablespace FROM pg_tables WHERE tablename = 'mytable';

Se for NULL, ele estará no espaço de tabela padrão:

SHOW default_tablespace;

Se isso é NULLassim, ele provavelmente vai ser pg_default(confira os documentos oficiais em caso é alterado).

Agora mova a mesa para cima:

ALTER TABLE mytable SET TABLESPACE tempspace;
COMMIT;  -- if autocommit is off

Vácuo:

VACUUM FULL mytable;

Mover para trás:

-- assuming you are using the defaults, the tablespace will be "pg_default".
-- Otherwise use the value from the SELECT we did earlier.
ALTER TABLE mytable SET TABLESPACE pg_default;
COMMIT;  -- if autocommit is off

Remova o espaço temporário:

DROP TABLESPACE tempspace;
exuma
fonte
NB: o movimento parece usar mais espaço em disco no diretório de dados original ...
Chris Withers
Apenas testei na 9.3 e funciona como um encanto.
Bartek Jablonski
Utilizado com sucesso na produção em 9.1. Após alterar o espaço de tabela, o espaço usado original é liberado. Observe que alta carga da CPU devido a operações de E / S pode ser esperada.
erny 29/07
2
Dicas incríveis, obrigado por esta explicação detalhada. Observe que no espaço de tabela temporário você precisará pelo menos size of table x 2, pois VACUUM FULLestá fazendo uma cópia completa da tabela.
Stéphane
Obrigado @ Stéphane. Eu adicionei as informações ao corpo principal.
Exhuma
2

Rapido e sujo:

  • Parar Postgres
  • Mova o diretório principal do banco de dados para outro disco em que haja espaço suficiente para aspirar
  • No local original de main, adicione um link simbólico para o novo local
  • Vácuo
  • Exclua o link simbólico e mova o diretório principal de volta ao seu local original
  • Iniciar o Postgres

Por exemplo,:

$ service postgresql stop $ mv /var/lib/postgresql/9.5/main /mnt/bigdisk $ ln -sr /mnt/bigdisk/main /var/lib/postgresql/9.5 $ vacuumdb --all --full $ rm /var/lib/postgresql/9.5/main $ mv /mnt/bigdisk/main /var/lib/postgresql/9.5 $ service postgresql start

Roger Dahl
fonte
0

Se você tiver espaço em disco para executar um despejo e restauração, deverá ter espaço em disco para executar um aspirador de pó - completo. O problema é que o vacuumdb --full fará uma cópia de todo o arquivo de dados. Então, o que você poderia fazer é:

  1. copie os arquivos que mantêm a grande mesa em uma unidade diferente, por exemplo, uma unidade maior e mais lenta.
  2. faça links simbólicos do local original para o novo local na outra unidade.
  3. execute vacuumdb --full, agora ele deve ler os dados do outro disco e gravar a tabela final no seu disco de dados original.
Gunther
fonte