Estou tentando descobrir a maneira mais rápida de:
- INSERIR uma linha se ela não existir
- SUBSTITUIR (todas as colunas de uma vez) a linha se existir
Eu pensei em DELETE
+ INSERT
, mas isso parece 2 scans e se eu fizer um INSERT
+ ON CONFLICT
, recebo uma consulta enorme onde tudo tem que ser duplicado.
Existe um método geralmente reconhecido para fazer isso?
Esse é um caso geralmente reconhecido para UPSERT (
INSERT ... ON CONFLICT .. DO UPDATE ...
).E o caso simples envolve apenas uma varredura de índice único . (Além de possíveis atualizações de bloqueio e gravação e índice.)
Por um lado, as condições de corrida sob carga de gravação simultânea geralmente são tratadas de maneira mais inteligente. Ver:
E também é normalmente mais barato. "REPLACE (todas as colunas de uma vez) a linha se existir" soa levemente suspeito. Se "a linha existe", pelo menos uma ou mais colunas devem ser idênticas. Por outro lado,
UPDATE
grava uma nova versão de linha em qualquer caso (se gravar). Isso ainda é mais barato queDELETE
+INSERT
se os campos torrados puderem ser transportados ou entradas de índice com um HOTUPDATE
. Ver:Sua "grande consulta onde tudo tem que ser duplicado" indica potencial para otimização ou possíveis mal-entendidos. Se for esse o caso, mostre a consulta que você tem, junto com sua versão do Postgres, uma configuração reproduzível e o resultado desejado (em uma nova pergunta!).
Dito isso, se você não tiver colunas torradas, nenhuma carga de gravação simultânea pesada e poucos índices (ou apenas um), então
DELETE
+INSERT
é apenas moderadamente mais caro.Ao substituir grandes partes de uma tabela sem carga de gravação simultânea, pode até ser mais barato. Você pode
VACUUM
a tabela entreDELETE
eINSERT
... Mas isso está fugindo do caso de uso na questão.