Wie schlimm ist das ignorieren Oracle DUP_VAL_ON_INDEX-exception?
Ich habe eine Tabelle, wo ich die Aufnahme, wenn ein Benutzer angeschaut hat, ein Objekt mindestens einmal, also:
HasViewed
ObjectID number (FK to Object table)
UserId number (FK to Users table)
Beiden Felder NICHT NULL sind, und bilden zusammen den Primärschlüssel.
Meine Frage ist, da ich egal wie oft jemand angezeigt hat, ein Objekt (nach dem ersten), habe ich zwei Möglichkeiten für das handling von Schneidplatten.
- Ein SELECT count(*) ... und wenn keine Datensätze gefunden werden, fügen Sie einen neuen Datensatz.
- Immer nur einen Datensatz einfügen, und wenn es wirft eine DUP_VAL_ON_INDEX Ausnahmen (die anzeigt, dass es schon so war, ein Rekord), ignorieren Sie es einfach.
Was ist die Kehrseite der Auswahl der zweiten option?
UPDATE:
Ich denke, der beste Weg, es zu setzen ist : "Ist der overhead, verursacht durch die Ausnahme, die schlimmer als der overhead, verursacht durch die anfängliche Auswahl?"
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde normalerweise einfach einfügen und trap die DUP_VAL_ON_INDEX-exception, da dies der einfachste code. Dies ist effizienter als die überprüfung auf die Existenz, bevor Sie. Ich denke nicht, dass dies zu tun, einen "schlechten Geruch" (furchtbarer Ausdruck!) weil die Ausnahme, die wir behandeln, ausgelöst durch Oracle - es ist nicht wie hebt Ihr Eure eigene Ausnahmen als flow-control-Mechanismus.
Dank Igor ' s Kommentar habe ich jetzt zwei verschiedene benchamrks auf dieser: (1) wo alle insert-versuche, außer der ersten, sind Duplikate, (2) wo alle Einsätze sind keine Duplikate. Die Realität liegt irgendwo zwischen den beiden Fällen.
Hinweis: tests an Oracle 10.2.0.3.0.
Fall 1: Überwiegend Duplikate
Es scheint, dass die meisten effizienter Ansatz (von einem signifikanten Faktor) ist zu prüfen, für die Existenz, WÄHREND einfügen:
Ergebnisse (nach einmal ausgeführt, um zu vermeiden, die Analyse der Gemeinkosten):
Fall 2: keine Duplikate
Ergebnisse:
In diesem Fall DUP_VAL_ON_INDEX gewinnt durch eine Meile. Beachten Sie die "select before insert" ist die langsamste, in beiden Fällen.
So scheint es, dass Sie sollten wählen Sie option 1 oder 3 entsprechend der relativen Wahrscheinlichkeit, fügt sein oder nicht-Duplikate.
Ich glaube nicht, dass es ein Nachteil für die zweite option. Ich denke, es ist ein absolut korrekter Verwendung der genannten Ausnahme, und es vermeidet die lookup-overhead.
Versuchen?
Sollte es wieder 1, wenn es eines gibt, sonst NULL.
In Ihrem Fall sieht es sicher ignorieren, aber für die Leistung, die man vermeiden sollte-Ausnahmen auf dem gemeinsamen Weg. Eine Frage zu Fragen, "Wie Häufig werden die Ausnahmen sein?"
Paar genug, um zu ignorieren? oder so manch andere Methode sollte verwendet werden?
In der Regel -, Ausnahme-Behandlung ist langsamer; aber wenn es passieren würde, nur selten, dann würden Sie vermeiden den Aufwand der Abfrage.
Ich denke, es hängt hauptsächlich von der Frequenz der Ausnahme, aber wenn die Leistung wichtig ist, würde ich vorschlagen, einige benchmarking mit beiden Ansätzen.
Generell, die Behandlung von gemeinsamen Veranstaltungen als Ausnahme ist ein schlechter Geruch; aus diesem Grund konnte man sehen, auch aus einer anderen Sicht.
Wenn es eine Ausnahme ist, dann sollte es behandelt werden, als die Ausnahme - und dein Vorgehen ist korrekt.
Wenn es ein common event, dann sollten Sie versuchen, explizit behandeln - und dann prüfen, ob der Datensatz bereits eingefügt.
IMHO ist es am besten zu gehen mit der Option 2: Andere als das, was bereits gesagt worden ist, sollten Sie überlegen, thread-Sicherheit. Wenn man mit option 1 und, Wenn mehrere threads Ihre PL/SQL-block, dann ist es möglich, dass zwei oder mehr threads Feuer wählen Sie in der gleichen Zeit und zu dieser Zeit gibt es keine Aufzeichnungen, diese werden am Ende alle führenden threads einfügen und Sie erhalten unique-constraint-Fehler.