sql >> Database teknologi >  >> RDS >> Oracle

Hvor slemt er det at ignorere Oracle DUP_VAL_ON_INDEX undtagelse?

Jeg ville normalt bare indsætte og fange undtagelsen DUP_VAL_ON_INDEX, da dette er den nemmeste at kode. Dette er mere effektivt end at tjekke for eksistensen før indsættelse. Jeg betragter ikke at gøre dette som en "dårlig lugt" (frygtelig sætning!), fordi den undtagelse, vi håndterer, er rejst af Oracle - det er ikke som at hæve dine egne undtagelser som en flowkontrolmekanisme.

Takket være Igors kommentar har jeg nu kørt to forskellige benchamrks på dette:(1) hvor alle insert-forsøg undtagen det første er dubletter, (2) hvor alle inserts ikke er dubletter. Virkeligheden vil ligge et sted mellem de to sager.

Bemærk:test udført på Oracle 10.2.0.3.0.

Tilfælde 1:For det meste dubletter

Det ser ud til, at den mest effektive tilgang (af en væsentlig faktor) er at kontrollere, om der findes, MENS man indsætter:

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

Resultater (efter at have kørt én gang for at undgå parsing af overhead):

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

Case 2:ingen dubletter

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

Resultater:

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

I dette tilfælde vinder DUP_VAL_ON_INDEX med en mile. Bemærk, at "vælg før indsættelse" er den langsomste i begge tilfælde.

Så det ser ud til, at du skal vælge mulighed 1 eller 3 i henhold til den relative sandsynlighed for, at indsatser er eller ikke er dubletter.



  1. Passer PostgreSQL's Ltree-modul godt til trådede kommentarer?

  2. alternativknapværdi for tilføjelse

  3. PostgreSQL 9.1 ved hjælp af collate i udvalgte udsagn

  4. Sammenligning af almindelige databaseinfrastrukturmønstre