VACUUM retornando espaço em disco para o sistema operacional

21

VACUUMgeralmente não retorna espaço em disco para o sistema operacional, exceto em alguns casos especiais.
Dos documentos:

O formato padrão VACUUMremove as versões de linha morta em tabelas e índices e marca o espaço disponível para reutilização futura. No entanto, ele não retornará o espaço para o sistema operacional, exceto no caso especial em que uma ou mais páginas no final de uma tabela ficam totalmente livres e um bloqueio exclusivo da tabela pode ser obtido facilmente. Por outro lado, VACUUM FULLcompacta ativamente as tabelas escrevendo uma nova versão completa do arquivo da tabela sem espaço morto. Isso minimiza o tamanho da tabela, mas pode levar muito tempo. Também requer espaço em disco extra para a nova cópia da tabela, até que a operação seja concluída.

A pergunta é: como esse banco de dados pode indicar quando one or more pages at the end of a table become entirely freeé alcançado? Isso pode ser feito via VACUUM FULL, mas não tenho espaço suficiente para implementá-lo. Então, existem outras possibilidades?

errado sobre tudo
fonte

Respostas:

29

Para retornar espaço ao sistema operacional, use VACUUM FULL. Enquanto estiver nisso, suponho que você corra VACUUM FULL ANALYZE. Cito o manual :

FULL

Seleciona o vácuo "cheio", que pode recuperar mais espaço , mas leva muito mais tempo e bloqueia exclusivamente a mesa. Esse método também requer espaço em disco extra, pois grava uma nova cópia da tabela e não libera a cópia antiga até que a operação seja concluída. Normalmente, isso só deve ser usado quando uma quantidade significativa de espaço precisa ser recuperada de dentro da tabela.

Negrito ênfase minha.

CLUSTER alcança isso também como um efeito colateral.

VACUUMNormalmente, a planície não atinge seu objetivo ( "uma ou mais páginas no final de uma tabela totalmente gratuitas" ). Ele não reordena as linhas e remove apenas as páginas vazias do final físico do arquivo quando a oportunidade surgir - como instruído pela cotação do manual.

Você pode obter páginas vazias no final do arquivo físico quando faz INSERTum lote de linhas e DELETEantes que outras tuplas sejam anexadas. Ou isso pode acontecer por coincidência se linhas suficientes forem excluídas.

Também há configurações especiais que podem impedir a VACUUM FULLrecuperação de espaço. Vejo:

Prepare páginas vazias no final de uma tabela para teste

A coluna do sistema ctidrepresenta a posição física de uma linha. Você precisa entender essa coluna:

Podemos trabalhar com isso e preparar uma tabela excluindo todas as linhas da última página:

DELETE FROM tbl t
USING (
   SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid     AS min_tid
        , (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
   FROM   tbl
   ORDER  BY ctid DESC
   LIMIT  1
   ) d
WHERE t.ctid BETWEEN d.min_tid AND d.max_tid;

Agora, a última página está vazia. Isso ignora gravações simultâneas. Você é o único que está escrevendo nessa tabela ou precisa bloquear a gravação para evitar interferências.

A consulta é otimizada para identificar linhas qualificadas rapidamente. O segundo número de a tidé o índice da tupla armazenado como não assinado int2e 65535é o máximo para esse tipo ( 2^16 - 1), portanto esse é o limite superior seguro.

SQL Fiddle (reutilizando uma tabela simples de um caso diferente.)

Ferramentas para medir o tamanho da linha / tabela:

Disco cheio

Você precisa de espaço de manobra no disco para qualquer uma dessas operações. Há também a ferramenta da comunidade pg_repackcomo substituta do VACUUM FULL/ CLUSTER. Evita bloqueios exclusivos, mas também precisa de espaço livre para trabalhar. O manual:

Requer espaço livre em disco duas vezes maior que a (s) tabela (s) e índices de destino.

Como último recurso, você pode executar um ciclo de despejo / restauração. Isso remove todo o inchaço das tabelas e índices também. Pergunta intimamente relacionada:

A resposta é muito radical. Se sua situação permitir (sem chaves estrangeiras ou outras referências que impedem exclusões de linha) e sem acesso simultâneo à tabela), você pode:

Despejar a tabela na conexão em disco de um computador remoto com muito espaço em disco ( -apara --data-only):

No shell remoto, despeje dados da tabela:

pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql

Em uma sessão da página, TRUNCATEa tabela:

-- drop all indexes and constraints here for best performance
TRUNCATE mytbl;

No shell remoto, restaure na mesma tabela:

psql -h <host_name> -p <port> mydb -f db_mytbl.sql
-- recreate all indexes and constraints here

Agora está livre de linhas mortas ou inchaço.

Mas talvez você possa ter isso mais simples?

  • Você pode liberar espaço suficiente no disco excluindo (movendo) arquivos não relacionados?

  • Você pode VACUUM FULLtabelas menores primeiro, uma por uma, liberando espaço em disco suficiente?

  • Você pode executar REINDEX TABLEou REINDEX INDEXliberar espaço em disco de índices inchados?

Faça o que fizer, não seja precipitado . Em caso de dúvida, faça backup de tudo primeiro em um local seguro.

Erwin Brandstetter
fonte
Erwin, desculpe, esqueci de mencionar que não tenho espaço suficiente para o vácuo cheio. Atualizado a pergunta.
wrong-sobre-tudo
@ Zapadlo: adicionei um capítulo para a pergunta atualizada.
Erwin Brandstetter 19/03/2013
Obrigado pela resposta abrangente. Na verdade, pensei em colocar linhas mortas no final das páginas de banco de dados com atualizações falsas, ou seja update table set field_1 = field_1, mas aspirar a mesa após essa operação não conseguiu retornar espaço livre, alguma idéia?
wrong-sobre-tudo
@ Zapadlo: As idéias que tive já estão na resposta. :) Não conheço uma ferramenta que possa reordenar tuplas mortas sem precisar de espaço de manobra substancial no disco. (Não significa que não pode haver um lá fora.)
Erwin Brandstetter
Eles dizem que esta ferramenta faz o truque, não tentei ainda que: code.google.com/p/pgtoolkit/source/browse/trunk/bin/...
mal-sobre-tudo