sql >> Databáze >  >> RDS >> Oracle

Jak špatné je ignorování výjimky Oracle DUP_VAL_ON_INDEX?

Normálně bych pouze vložil a zachytil výjimku DUP_VAL_ON_INDEX, protože toto je nejjednodušší kódování. To je efektivnější než kontrola existence před vložením. Nepovažuji to za „špatný zápach“ (příšerná fráze!), protože výjimku, kterou zpracováváme, vyvolává Oracle – není to jako vytvářet vlastní výjimky jako mechanismus řízení toku.

Díky Igorovu komentáři jsem na to nyní provedl dva různé benchamrky:(1) kde všechny pokusy o vložení kromě prvního jsou duplikáty, (2) kde všechny vložení nejsou duplikáty. Realita bude ležet někde mezi těmito dvěma případy.

Poznámka:testy provedené na Oracle 10.2.0.3.0.

Případ 1:Většinou duplikáty

Zdá se, že nejúčinnějším přístupem (s významným faktorem) je kontrola existence BĚHEM vkládání:

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

Výsledky (po jednom spuštění, aby se zabránilo režii analýzy):

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

Případ 2:žádné duplikáty

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

Výsledky:

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

V tomto případě DUP_VAL_ON_INDEX vyhrává o míli. Všimněte si, že "vybrat před vložením" je v obou případech nejpomalejší.

Zdá se tedy, že byste měli zvolit možnost 1 nebo 3 podle relativní pravděpodobnosti, že vložky budou nebo nebudou duplikáty.



  1. Kartézské součiny a výběry v klauzuli od

  2. From Now() to Current_timestamp v Postgresql

  3. Odhad mohutnosti:Kombinace statistik hustoty

  4. Android program pro převod databáze SQLite do excelu