Oracle
 sql >> база данни >  >> RDS >> Oracle

Колко лошо е игнорирането на Oracle DUP_VAL_ON_INDEX изключение?

Обикновено просто бих вмъкнал и прихванал изключението DUP_VAL_ON_INDEX, тъй като това е най-лесното за кодиране. Това е по-ефективно от проверката за съществуване преди вмъкване. Не считам това за „лоша миризма“ (ужасна фраза!), защото изключението, което обработваме, се генерира от Oracle – не е като да създавате свои собствени изключения като механизъм за контрол на потока.

Благодарение на коментара на Игор, сега изпълних два различни benchamrks за това:(1) където всички опити за вмъкване с изключение на първия са дубликати, (2) където всички вмъквания не са дубликати. Реалността ще се намира някъде между двата случая.

Забележка:тестовете са извършени на Oracle 10.2.0.3.0.

Случай 1:Предимно дубликати

Изглежда, че най-ефективният подход (по значим фактор) е да се провери за съществуване ДОКАТО вмъквате:

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

Резултати (след еднократно изпълнение, за да се избегнат допълнителни разходи за анализ):

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

Случай 2:без дубликати

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

Резултати:

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

В този случай DUP_VAL_ON_INDEX печели с една миля. Забележете, че „избиране преди вмъкване“ е най-бавното и в двата случая.

Така че изглежда, че трябва да изберете опция 1 или 3 според относителната вероятност вложките да бъдат или да не са дубликати.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да премахнете скритите двойни кавички в стойностите на колоните на SQL Developer

  2. Oracle Query дава грешка

  3. Как да конфигурирате низа за връзка за ODP.NET низ за връзка с FailOver?

  4. Как да свържете Airflow към базата данни на Oracle

  5. не може да запише данни с голям размер с UTL_FILE.PUT_LINE