Oracle
 sql >> Baza danych >  >> RDS >> Oracle

Jak złe jest ignorowanie wyjątku Oracle DUP_VAL_ON_INDEX?

Zwykle po prostu wstawiam i łapie wyjątek DUP_VAL_ON_INDEX, ponieważ jest to najprostszy kod. Jest to bardziej wydajne niż sprawdzanie istnienia przed wstawieniem. Nie uważam tego za "nieprzyjemny zapach" (okropna fraza!), ponieważ wyjątek, który obsługujemy, jest zgłaszany przez Oracle - to nie jest jak podnoszenie własnych wyjątków jako mechanizmu kontroli przepływu.

Dzięki komentarzowi Igora uruchomiłem teraz dwa różne testy porównawcze:(1) gdzie wszystkie próby wstawienia oprócz pierwszej są duplikatami, (2) gdzie wszystkie wstawki nie są duplikatami. Rzeczywistość będzie leżała gdzieś pomiędzy tymi dwoma przypadkami.

Uwaga:testy przeprowadzone na Oracle 10.2.0.3.0.

Przypadek 1:głównie duplikaty

Wydaje się, że najskuteczniejszym podejściem (z uwagi na istotny czynnik) jest sprawdzenie istnienia PODCZAS wstawiania:

Monit
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;
/

Wyniki (po jednokrotnym uruchomieniu, aby uniknąć analizowania kosztów ogólnych):

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

Przypadek 2:brak duplikatów

Monit
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;
/

Wyniki:

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

W tym przypadku DUP_VAL_ON_INDEX wygrywa o milę. Zauważ, że "wybierz przed wstawieniem" jest najwolniejszy w obu przypadkach.

Wygląda więc na to, że powinieneś wybrać opcję 1 lub 3 w zależności od względnego prawdopodobieństwa, że ​​wstawki są lub nie są duplikatami.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zapytania hierarchiczne

  2. Zwróć wyniki zapytania jako listę oddzieloną przecinkami w Oracle

  3. libaio.so.1:nie można otworzyć pliku obiektu współdzielonego

  4. Tworzenie pliku CSV na pętlę | PLSQL Oracle SQL Developer

  5. Wymiana części pakietu Oracle