sql >> Databasteknik >  >> RDS >> Oracle

Hur dåligt är det att ignorera Oracle DUP_VAL_ON_INDEX-undantaget?

Jag skulle normalt sett bara infoga och fälla undantaget DUP_VAL_ON_INDEX, eftersom detta är det enklaste att koda. Detta är mer effektivt än att kontrollera om det finns innan du infogar. Jag anser inte att det här är en "dålig lukt" (hemsk fras!) eftersom undantaget vi hanterar tas upp av Oracle - det är inte som att ta upp dina egna undantag som en flödeskontrollmekanism.

Tack vare Igors kommentar har jag nu kört två olika benchamrks på detta:(1) där alla insättningsförsök utom det första är dubbletter, (2) där alla insättningar inte är dubbletter. Verkligheten kommer att ligga någonstans mellan de två fallen.

Obs:tester utförda på Oracle 10.2.0.3.0.

Fall 1:Mestadels dubbletter

Det verkar som att det mest effektiva tillvägagångssättet (av en betydande faktor) är att kontrollera om det finns UNDER du infogar:

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

Resultat (efter att ha kört en gång för att undvika att analysera omkostnader):

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:inga dubbletter

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

Resultat:

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 det här fallet vinner DUP_VAL_ON_INDEX med en mil. Observera att "välj före infogning" är långsammast i båda fallen.

Så det verkar som att du bör välja alternativ 1 eller 3 beroende på den relativa sannolikheten för att inlägg är eller inte är dubbletter.



  1. Hur man skapar en databasdriven navigeringsmeny på flera nivåer med Laravel

  2. Bygga en mycket tillgänglig databas för Moodle med PostgreSQL

  3. Primärnyckel i SQL:Allt du behöver veta om primärnyckeloperationer

  4. On-Premises vs. SaaS:Databas Monitoring System Architecture