CEVIU Logo
Voltar

No PostgreSQL, exclusão em larga escala só escala com DROP TABLE, não com DELETE

Aprofundamento CEVIU

Aprofundamento

O DELETE no PostgreSQL não apaga dados, ele marca tuplas como mortas, mantendo versões antigas para garantir isolamento de transações via MVCC. Cada linha carrega os campos xmin e xmax, que definem sua visibilidade. Quando você apaga 10 milhões de linhas, o banco cria 10 milhões de tuplas mortas. Elas só saem do disco com VACUUM, e se houver uma transação longa bloqueando a limpeza, o bloat explode.

TRUNCATE e DROP TABLE ignoram esse ciclo: descartam arquivos físicos em um único passo, sem gerar WAL massivo nem depender de autovacuum. Em benchmarks reais, TRUNCATE em 47 milhões de linhas leva menos de 1 segundo; DELETE leva horas e pode encher o WAL com centenas de GB. Isso não é otimização, é escolha arquitetural: se você precisa excluir em massa, seu schema deve ser feito para trocar partições, não para deletar linhas.

O que mudou

A cobertura anterior de 13 de abril já alertava sobre o acúmulo de dead tuples em filas de jobs, mas tratava como problema operacional secundário. Agora, a recomendação mudou de 'ajuste o autovacuum' para 'reprojete o schema'. O artigo de 20 de abril explicava o MVCC teoricamente, hoje sabemos que essa arquitetura torna DELETE em larga escala tecnicamente inviável em produção. E o benchmark de 1º de maio identificou contenção de lock de tabela como gargalo: agora sabemos que DELETE é um dos principais causadores disso, especialmente em workloads concorrentes.

Por que isso importa

Desenvolvedores que usam Postgres como fila, log ou armazenamento de séries temporais estão sob risco silencioso: cada DELETE em massa degrada desempenho, aumenta custo de I/O e compromete a replicação. A mudança não é só técnica, é de mentalidade. Trocar uma operação lógica (DELETE) por uma estrutural (DROP PARTITION) exige pensar em particionamento desde o início, usar tabelas temporárias com atomicidade de troca (CREATE TABLE AS + ALTER TABLE ... RENAME TO), e abandonar padrões herdados de bancos que não usam MVCC. É menos sobre escrever SQL e mais sobre projetar ciclos de vida de dados.

Linha do tempo

  1. Alerta sobre degradação de filas por acúmulo de dead tuples bloqueando VACUUM

  2. Explicação detalhada do MVCC e papel dos campos xmin/xmax na visibilidade de tuplas

  3. Identificação de contenção de lock de tabela como gargalo principal em workloads intensos

  4. Recomendação técnica consolidada: exclusão em larga escala deve ser estrutural (DROP/TRUNCATE), não lógica (DELETE)

Perguntas frequentes

Posso usar TRUNCATE em vez de DELETE em qualquer caso?

Não. TRUNCATE é DDL, não DML: limpa toda a tabela, ignora triggers, não rola em transações aninhadas e requer privilégios de owner. Se você precisa excluir apenas um subconjunto condicional (ex: WHERE status = 'cancelled'), DELETE ainda é necessário, mas nesse caso, prefira particionar por status ou data para transformar a condição em troca de partição.

E se eu já tenho bloat acumulado? Como limpo sem downtime?

VACUUM FULL bloqueia a tabela. Use pg_repack: reescreve a tabela online, sem locks exclusivos. Para índices, use REINDEX CONCURRENTLY. Mas atenção: isso é paliativo. O foco deve ser prevenir bloat com design estrutural, não consertá-lo depois.

PostgreSQL 17 e 18 resolvem o problema do DELETE em larga escala?

Não resolvem o problema central, o MVCC continua exigindo marcação de tuplas mortas. A v17 reduziu consumo de memória do VACUUM em até 20×. A v18 traz E/S assíncrona e escalonamento dinâmico do autovacuum. São melhorias importantes, mas não eliminam a necessidade de evitar DELETE em massa. São ferramentas para conter o dano, não para permitir o erro.

TimescaleDB resolve isso para séries temporais?

Sim, parcialmente. A função DROP_CHUNKS() é equivalente a DROP TABLE em uma partição, rápida, sem bloat. TimescaleDB 2.21 acelera DELETE em até 42× ao evitar descompressão desnecessária, mas ainda gera dead tuples. A solução ideal permanece: use chunks para retenção, não DELETE condicional.

Fontes

Avalie este artigo:
Compartilhar:
Categoria
CEVIU Web Dev
Publicado
15 de junho de 2026
Editoria
CEVIU Web Dev

Quer receber mais sobre CEVIU Web Dev?

Conteúdo curado diariamente, direto no seu e-mail.

Conteúdo curado diariamenteDiversas categoriasCancele quando quiser
No PostgreSQL, exclusão em larga escala só escala com DROP