Gostaria de saber qual seria a maneira mais eficiente de excluir um grande número de linhas do PostgreSQL, esse processo faria parte de uma tarefa recorrente todos os dias para importar dados em massa (um delta de inserções + exclusões) em uma tabela. Pode haver milhares, potencialmente milhões de linhas para excluir.
Eu tenho um arquivo de chaves primárias, uma por linha. As duas opções em que eu pensava estavam ao longo das linhas abaixo, mas não conheço o suficiente dos internos do PostgreSQL para tomar uma decisão informada que seria melhor.
- Execute uma
DELETE
consulta para cada linha do arquivo, com umaWHERE
chave primária simples (ou agrupe as exclusões em lotes den
usando umaIN()
cláusula) - Importe as chaves primárias para uma tabela temporária usando o
COPY
comando e exclua da tabela principal usando uma junção
Qualquer sugestão será muito apreciado!
postgresql
delete
bulk
Tarnfeld
fonte
fonte
Respostas:
Sua segunda opção é muito mais limpa e funcionará bem o suficiente para fazer isso valer a pena. Sua alternativa é criar consultas gigantescas, o que será bastante trabalhoso para planejar e executar. Em geral, será melhor deixar o PostgreSQL fazer o trabalho aqui. Em geral, encontrei atualizações em dezenas de milhares de linhas da maneira que você está descrevendo para executar adequadamente, mas há uma coisa importante a ser evitada.
A maneira de fazer isso é usar um select e um join na sua exclusão.
Sob nenhuma circunstância você deve fazer o seguinte com uma tabela grande:
Isso geralmente causa um antijoin de loop aninhado, o que torna o desempenho bastante problemático. Se você precisar seguir esse caminho, faça o seguinte:
O PostgreSQL geralmente é muito bom para evitar planos ruins, mas ainda existem casos envolvendo junções externas que podem fazer uma grande diferença entre planos bons e ruins.
Isso está vagando um pouco mais longe, mas acho que vale a pena mencionar por causa de quão fácil é ir do IN para o NOT IN e assistir ao tanque de desempenho da consulta.
fonte
IN ( select id from foo except select id from rows_to_keep )
veja postgresql.org/docs/9.4/static/queries-union.htmlMe deparei com essa pergunta porque tinha um problema semelhante. Estou limpando um banco de dados com mais de 300 milhões de linhas; o banco de dados final terá apenas cerca de 30% dos dados originais. Se você estiver enfrentando um cenário semelhante, é realmente mais fácil inserir uma nova tabela e indexar novamente em vez de excluir.
Faça algo como
Com a indexação adequada em foo e bar, você pode evitar verificações de Seq.
Então você teria que re-indexar e renomear a tabela.
fonte