Prós e contras de verificar se existe valor para uma coluna exclusiva ou se o db gera um erro exclusivo ao inserir

8

Enquanto escrevia uma consulta outro dia, um pensamento me ocorreu e ficou na minha mente.

O que é preferível, primeiro verificar se existe um valor para uma coluna exclusiva e depois inserir ou inserir e permitir que o banco de dados apresente erro de restrição exclusivo? Será que isso importa?

Edit: Como sugerido abaixo, em resposta, que esse problema depende do banco de dados. Estou adicionando a tag postgresql.

codecool
fonte

Respostas:

3

Não acho que sua pergunta seja realmente independente de banco de dados. A resposta correta pode depender dos detalhes da implementação, que podem variar de fornecedor para fornecedor e mudar para a próxima versão. Eu testaria com simultaneidade antes de escolher qualquer abordagem em qualquer RDBMS.

No momento, no SQL Server 2008 R2, estou usando o seguinte:

  1. Baixa concorrência e baixa quantidade de modificações. Para salvar uma única linha, serializo usando sp_getapplock e use MERGE. Realizo teste de estresse com alta simultaneidade para verificar se funciona.

  2. Maior simultaneidade e / ou volume. Para evitar simultaneidade e aumentar o desempenho, não salvo uma linha por vez. Eu acumulo alterações no meu servidor de aplicativos e uso TVPs para salvar lotes. Ainda, para evitar problemas relacionados à concorrência, serializo usando sp_getapplock antes do MERGE. Novamente, enfatizo o teste com alta simultaneidade para verificar se funciona.

Como resultado, temos um bom desempenho e zero problemas relacionados à simultaneidade na produção: sem conflitos, sem violações de PK / restrições exclusivas etc.

AK
fonte
Então, você quer dizer que, se os problemas de simultaneidade forem bem tratados, verificar primeiro é uma boa idéia?
Codecool
11
Sim, geralmente evitar erros tem um desempenho melhor do que lançar e capturar exceções, mas você precisa compará-lo em sua plataforma.
AK
7

Deixe o banco de dados gerar um erro.

Testar primeiro não é seguro para simultaneidade, pois você poderá ter uma colisão, porque 2 threads podem passar no "NOT EXIST" e ambos tentarão escrever. Isso se aplica às estratégias de bloqueio "READ COMMITTED" e MVCC / Snapshot.

Você pode usar dicas de bloqueio para forçar o isolamento, mas reduz o desempenho.

Eu chamo isso de padrão JFDI (link SO). Para "atualizar se existir", consulte isso aqui: Precisa de ajuda para solucionar o cenário de conflito do Sql Server 2005 . Estes são o SQL Server. O MySQL possui INSERT IGNORE, que lida com isso normalmente. Não tenho certeza sobre o resto

gbn
fonte
okk. Eu não pensei nisso! Em caso de simultaneidade, a verificação pode falhar. :)
codecool
Eu acho que é útil realizar a verificação (e falhar normalmente), mas seguir o ditado "confie, mas verifique" para detectar a falha. O motivo? O tratamento de erros é caro. Atualmente, estou trabalhando em alguns testes que devem revelar se esse comentário faz sentido. Se esse comentário desaparecer, você saberá o resultado. :-)
Aaron Bertrand
Também em 2008, MERGEpode ter resolvido as observações de Paul, mas não testei isso em altas taxas de câmbio. Principalmente porque ainda tenho que treinar meu cérebro para entender essa sintaxe.
Aaron Bertrand
11
Mea culpa. Fiz algumas observações nos meus testes hoje. Lembre-se de que são testes muito isolados, sem simultaneidade. Para pastilhas retas, verificar primeiro e evitar o erro é cerca de 10 vezes mais rápido do que permitir que o erro ocorra. Mas em outros casos em que você fará um tratamento de erro mais complexo (TRY / CATCH ou IF @@ ERROR <> 0, com ROLLBACK ou THROW, etc.), é duas vezes mais lento se você verificar primeiro. Mais uma vez, vou enfatizar que essas são apenas minhas observações iniciais e há muitos fatores que podem influenciar o impacto que ela pode ter. Pode levar algum tempo até que eu possa escrever um blog sobre isso completamente.
Aaron Bertrand