Avantages et inconvénients de la vérification s'il existe une valeur pour une colonne unique ou laissez db générer une erreur unique lors de l'insertion

8

En écrivant une requête un autre jour, une pensée m'est venue et est restée dans mon esprit.

Qu'est-ce qui est préférable, d'abord vérifier si une valeur pour une colonne unique existe, puis insérer ou insérer et laisser db générer une erreur de contrainte unique? Cela importera-t-il même?

Edit: Comme suggéré ci-dessous pour répondre que ce problème dépend de la base de données, j'ajoute la balise postgresql.

codecool
la source

Réponses:

3

Je ne pense pas que votre question soit vraiment indépendante des bases de données. La bonne réponse peut dépendre des détails d'implémentation, qui peuvent varier d'un fournisseur à l'autre et changer avec la prochaine version. Je testerais sous simultané avant de choisir une approche sur n'importe quel SGBDR.

En ce moment, sur SQL Server 2008 R2, j'utilise ce qui suit:

  1. Faible simultanéité et faible quantité de modifications. Pour enregistrer une seule ligne, je sérialise à l'aide de sp_getapplock et utilise MERGE. Je teste les contraintes sous une concurrence élevée pour vérifier que cela fonctionne.

  2. Concurrence et / ou volume plus élevés. Pour éviter la concurrence et augmenter les performances, je n'enregistre pas une ligne à la fois. J'accumule des modifications sur mon serveur d'applications et j'utilise des TVP pour enregistrer des lots. Pourtant, pour éviter les problèmes liés à la concurrence, je sérialise en utilisant sp_getapplock avant le MERGE. Encore une fois, je soumets à un test de stress sous forte concurrence pour vérifier que cela fonctionne.

En conséquence, nous avons de bonnes performances et aucun problème lié à la concurrence en production: pas de blocages, pas de violation de PK / contraintes uniques, etc.

AK
la source
donc vous voulez dire que si les problèmes de simultanéité sont bien gérés, vérifier d'abord est une bonne idée?
codecool
1
Oui, éviter les erreurs est généralement plus efficace que lever et intercepter des exceptions, mais vous devez les comparer sur votre plate-forme.
AK
7

Laissez la base de données générer une erreur.

Tester d'abord n'est pas sûr pour la simultanéité car vous obtiendrez éventuellement une collision car 2 threads peuvent passer le "NON EXIST" et les deux essaieront d'écrire. Cela s'applique à la fois aux stratégies de verrouillage "LECTURE COMMISE" et MVCC / Snapshot.

Vous pouvez utiliser des conseils de verrouillage pour forcer l'isolement, mais vous réduisez les performances.

J'appelle cela le modèle JFDI (lien SO). Pour la «mise à jour s'il existe», consultez cette page ici: Besoin d'aide pour résoudre le scénario de blocage de SQL Server 2005 . Ce sont SQL Server. MySQL a INSERT IGNORE qui gère cela avec élégance. Pas sûr du reste

gbn
la source
ok. Je n'y ai pas pensé! En cas de simultanéité, même la vérification peut échouer. :)
codecool
Je pense qu'il est utile à la fois d'effectuer la vérification (et d'échouer gracieusement) mais de suivre l'adage «faire confiance mais vérifier» pour rattraper l'échec. La raison? La gestion des erreurs coûte cher. Je travaille sur des tests aujourd'hui, en fait, qui devraient révéler si ce commentaire est logique. Si ce commentaire disparaît, vous connaissez le résultat. :-)
Aaron Bertrand
En 2008 également, il y en a MERGEqui ont peut-être résolu les observations de Paul, mais je n'ai pas testé cela à des taux d'émission élevés. Surtout parce que je n'ai pas encore entraîné mon cerveau à comprendre cette syntaxe.
Aaron Bertrand
1
Mea culpa. J'ai fait quelques observations lors de mes tests aujourd'hui. Gardez à l'esprit qu'il s'agit de tests très isolés sans concurrence. Pour les insertions droites, vérifier d'abord et éviter l'erreur est environ 10 fois plus rapide que de laisser l'erreur se produire. Mais dans d'autres cas où vous allez faire une gestion d'erreurs plus complexe (TRY / CATCH ou IF @@ ERROR <> 0, avec ROLLBACK ou THROW, etc.), c'est environ deux fois plus lent si vous vérifiez d'abord. Encore une fois, je soulignerai que ce ne sont que mes observations initiales et de nombreux facteurs peuvent influencer l'impact que cela peut avoir. Il faudra peut-être un certain temps avant que je puisse bloguer à ce sujet en profondeur.
Aaron Bertrand