Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Wie schlimm ist das Ignorieren der Oracle DUP_VAL_ON_INDEX-Ausnahme?

Normalerweise würde ich einfach die Ausnahme DUP_VAL_ON_INDEX einfügen und abfangen, da dies am einfachsten zu codieren ist. Dies ist effizienter, als vor dem Einfügen auf Vorhandensein zu prüfen. Ich betrachte dies nicht als "schlechten Geruch" (schrecklicher Ausdruck!), da die von uns behandelte Ausnahme von Oracle ausgelöst wird - es ist nicht so, als würden Sie Ihre eigenen Ausnahmen als Flusskontrollmechanismus auslösen.

Dank Igors Kommentar habe ich jetzt zwei verschiedene Benchmarks dazu durchgeführt:(1) wo alle Einfügeversuche außer dem ersten Duplikate sind, (2) wo alle Einfügungen keine Duplikate sind. Die Realität wird irgendwo zwischen den beiden Fällen liegen.

Hinweis:Tests durchgeführt auf Oracle 10.2.0.3.0.

Fall 1:Meist Duplikate

Es scheint, dass der effizienteste Ansatz (um einen erheblichen Faktor) darin besteht, die Existenz zu überprüfen, WÄHREND des Einfügens:

prompt 1) Check DUP_VAL_ON_INDEX
begin
   for i in 1..1000 loop
      begin
         insert into hasviewed values(7782,20);
      exception
         when dup_val_on_index then
            null;
      end;
   end loop
   rollback;
end;
/

prompt 2) Test if row exists before inserting
declare
   dummy integer;
begin
   for i in 1..1000 loop
      select count(*) into dummy
      from hasviewed
      where objectid=7782 and userid=20;
      if dummy = 0 then
         insert into hasviewed values(7782,20);
      end if;
   end loop;
   rollback;
end;
/

prompt 3) Test if row exists while inserting
begin
   for i in 1..1000 loop
      insert into hasviewed
      select 7782,20 from dual
      where not exists (select null
                        from hasviewed
                        where objectid=7782 and userid=20);
   end loop;
   rollback;
end;
/

Ergebnisse (nach einmaliger Ausführung zur Vermeidung von Parsing-Overheads):

1) Check DUP_VAL_ON_INDEX

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.54
2) Test if row exists before inserting

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.59
3) Test if row exists while inserting

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.20

Fall 2:keine Duplikate

prompt 1) Check DUP_VAL_ON_INDEX
begin
   for i in 1..1000 loop
      begin
         insert into hasviewed values(7782,i);
      exception
         when dup_val_on_index then
            null;
      end;
   end loop
   rollback;
end;
/

prompt 2) Test if row exists before inserting
declare
   dummy integer;
begin
   for i in 1..1000 loop
      select count(*) into dummy
      from hasviewed
      where objectid=7782 and userid=i;
      if dummy = 0 then
         insert into hasviewed values(7782,i);
      end if;
   end loop;
   rollback;
end;
/

prompt 3) Test if row exists while inserting
begin
   for i in 1..1000 loop
      insert into hasviewed
      select 7782,i from dual
      where not exists (select null
                        from hasviewed
                        where objectid=7782 and userid=i);
   end loop;
   rollback;
end;
/

Ergebnisse:

1) Check DUP_VAL_ON_INDEX

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.15
2) Test if row exists before inserting

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.76
3) Test if row exists while inserting

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.71

In diesem Fall gewinnt DUP_VAL_ON_INDEX um Längen. Beachten Sie, dass "Vor dem Einfügen auswählen" in beiden Fällen am langsamsten ist.

Es scheint also, dass Sie Option 1 oder 3 entsprechend der relativen Wahrscheinlichkeit wählen sollten, ob Beilagen Duplikate sind oder nicht.