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.
VACUUM
Normalmente, 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 INSERT
um lote de linhas e DELETE
antes 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 FULL
recuperação de espaço. Vejo:
Prepare páginas vazias no final de uma tabela para teste
A coluna do sistema ctid
representa 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 int2
e 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_repack
como 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 ( -a
para --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, TRUNCATE
a 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 FULL
tabelas menores primeiro, uma por uma, liberando espaço em disco suficiente?
Você pode executar REINDEX TABLE
ou REINDEX INDEX
liberar 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.
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?