Comment le mauvais est ignorant Oracle DUP_VAL_ON_INDEX exception?
J'ai une table où je suis l'enregistrement si un utilisateur a consulté un objet au moins une fois, d'où:
HasViewed
ObjectID number (FK to Object table)
UserId number (FK to Users table)
Les deux champs ne sont PAS NULL et, ensemble, forment la Clé Primaire.
Ma question est, depuis je ne m'inquiète pas combien de fois quelqu'un a vu un objet (après le premier), j'ai deux options de gestion des inserts.
- Faire un SELECT count(*) ... et si aucun enregistrement n'est trouvé, insérer un nouvel enregistrement.
- Toujours il suffit d'insérer un disque, et si il jette un DUP_VAL_ON_INDEX exceptions (indiquant qu'il existait déjà un tel enregistrement), juste l'ignorer.
Quel est l'inconvénient de choisir la deuxième option?
Mise à JOUR:
Je suppose que la meilleure façon de le dire est : "Est la surcharge causée par l'exception de pire que la surcharge causée par le select initial?"
OriginalL'auteur James Curran | 2008-12-08
Vous devez vous connecter pour publier un commentaire.
Je devrais normalement il suffit de l'insérer et de piéger le DUP_VAL_ON_INDEX exception, comme c'est le plus simple à coder. C'est plus efficace que la vérification de l'existence du fichier avant de l'insérer. Je ne pas envisager de faire une "mauvaise odeur" (horrible expression!) parce que l'exception nous nous occupons est soulevée par Oracle - ce n'est pas comme élever vos propres exceptions en tant que flux de mécanisme de contrôle.
Grâce à Igor commentaire que j'ai maintenant exécuter deux benchamrks sur ceci: (1) lorsque toutes les tentatives d'insertion à l'exception de la première sont des doublons, (2) où tous les inserts ne sont pas des doublons. La réalité se situe entre les deux cas.
Remarque: les tests effectués sur Oracle 10.2.0.3.0.
Cas 1: la Plupart des doublons
Il semble que l'approche la plus efficace (par un facteur significatif) est de vérifier l'existence lors de l'insertion d':
Résultats (après avoir exécuté une fois pour éviter de l'analyse des frais généraux):
Cas 2: pas de doublons
Résultats:
Dans ce cas DUP_VAL_ON_INDEX gagne par un mile. Note le "select avant d'insérer" est le plus lent dans les deux cas.
Il semble donc que, vous devez choisir l'option 1 ou 3 en fonction de la probabilité relative de l'insère être ou ne pas être des doublons.
Le test est là où il y a des doublons. Quelle est la performance comme quand la nouvelle ligne n'est pas un doublon (c'est à dire celui avec la vérification explicite est encore en train de faire le chèque, mais le gestionnaire d'exception n'a pas besoin de coup de pied dans).
OriginalL'auteur Tony Andrews
Je ne pense pas qu'il existe un inconvénient à ce que votre deuxième option. Je pense que c'est une utilisation parfaitement valide de l'nommé exception, et en plus il évite la recherche de surcharge.
OriginalL'auteur kurosch
Essayer ce?
Il doit retourner 1, si il y en a un là, sinon NULL.
Dans votre cas, il semble sûr d'ignorer, mais pour la performance, il convient d'éviter d'exceptions sur le chemin commun. Une question à poser la question "Comment la volonté commune des exceptions?"
Assez peu d'ignorer? ou tant d'autre méthode doit être utilisée?
Yep. Je pense sql, et c'est un pl/sql question.
OriginalL'auteur EvilTeach
Généralement, la gestion des exceptions est plus lent, mais si elle ne se produit que rarement, alors vous voulez éviter la surcharge de la requête.
Je pense que ça dépend surtout de la fréquence de l'exception, mais si les performances sont importantes, je voudrais suggérer quelques comparaisons avec les deux approches.
En règle générale, le traitement commun des événements d'exception est une mauvaise odeur; pour cette raison, vous pourriez voir aussi à partir d'un autre point de vue.
Si c'est une exception, elle doit être traitée comme une exception, et que votre approche est correcte.
Si c'est un événement commun, alors vous devriez essayer de traiter explicitement - et puis vérifier si le disque est déjà inséré.
Je ne suis pas d'accord. Le nom même d ' "exception", nous dit exceptions ne doit pas être utilisé pour les flux de programme normal, peu importe leur origine. Sinon c'est une mauvaise odeur. Par ailleurs, votre réponse démontrer que la prévention de l'exception est le moyen le plus rapide (voir les résultats pour "Tester si la ligne existe lors de l'insertion").
Non, il ne le fait pas, il démontre exactement le contraire! Il est ridicule de ne pas utiliser le meilleur outil pour le travail juste parce que vous n'aimez pas l'odeur de "" son nom!!!!
OriginalL'auteur rob
À mon humble avis il est préférable d'aller avec l'Option 2: d'Autres que ce qui est déjà dit, vous devriez envisager de la sécurité des threads. Si vous allez à l'option 1 et Si plusieurs threads d'exécution de votre PL/SQL bloc alors il est possible que deux ou plusieurs fils de feu sélectionnez dans le même temps, et à ce moment il n'existe aucun enregistrement, ce sera la fin de leader sur tous les threads d'insérer et vous obtiendrez contrainte unique erreur.
OriginalL'auteur user961954