Estou construindo um aplicativo que buscará mensagens com JSON de vez em quando e as armazenará em um banco de dados postgres. Agora, quero evitar duplicatas, então calculo o sha-512 da mensagem e o defino como chave primária. Como quero evitar duplicatas, posso fazer duas coisas:
- Buscar todos os hashes do banco de dados e ver ao inserir novas mensagens se o hash já existe (verificando no código)
- Use um insert ignore (no postgres provavelmente uma atualização, já que o postgres não suporta insert ignore) e deixe o banco de dados lidar com essas exceções
Considerando que provavelmente estarei inserindo algumas mensagens por vez, gostaria de saber se o método dois procurará a chave primária e verificará se existe para cada inserção, em vez de apenas armazenar uma lista na memória com o método 1. O que seria mais eficiente?
PostgreSQL não tem,
INSERT ... IGNORE
então não é uma opção. Você pode usar operações do tipo upsert (procure por "postgresql upsert), mas elas certamente têm um custo de desempenho. Inserir e ignorar o erro resultante na chave duplicada é possível, mas tende a resultar em logs bastante spam.Pessoalmente, eu faria o que é efetivamente fazer um upsert em massa, onde faria algo assim:
CREATE TEMPORARY TABLE staging_table(...)
COPY TO staging_table(...) FROM ...
(ou faça inserções em massa)LOCK TABLE real_table IN EXCLUSIVE MODE
INSERT INTO real_table(...) SELECT col1,col2,col3,... FROM staging_table WHERE NOT EXISTS (SELECT 1 FROM real_table WHERE real_table.primarykey = staging_table.primarykey)
COMMIT
Você pode fazer um
UPDATE
antesINSERT
, se quiser, atualizando os registros existentes com novos valores.O
LOCK TABLE
é necessário para evitar que as atualizações simultâneas falhem com erros. Você ainda podeSELECT
da mesa durante a atualização.Se você tem
EXPLAIN
o plano para o seuINSERT
, deve ver que ele foi transformado em umJOIN
quando você está inserindo um número maior de registros.