回答

收藏

忽略Oracle DUP_VAL_ON_INDEX异常有多严重?

技术问答 技术问答 248 人阅读 | 0 人回复 | 2023-09-14

如果用户至少查看一次对象,我有一个表要记录:6 {2 K5 A8 \: J4 B5 s2 u
    HasViewed     ObjectID  number (FK to Object table)     UserId    number (FK to Users table)这两个字段都不是空的,一起形成主键。
9 c" O2 s: i9 e: x$ N7 `5 y& {我的问题是,我有两种选择来处理插入,因为我不在乎某人检查对象的次数(第一次之后)。
* u- ]  Z! `% A; I1 ~% L' X进行SELECT count(*)…,如未找到任何记录,则插入新记录。
3 e- p- q6 R1 e! J; x总是只插入一个记录,如果它导致DUP_VAL_ON_INDEX异常(表明有这样的记录)被忽略。
选择第二种选择的不利之处是什么?
0 h& L1 G2 v# S$ R; W1 _更新:
7 D% H# M8 M0 Z我认为最好的表达方式是:异常引起的费用是否比初始选择引起的费用更差?
9 T: x  N2 t7 D8 u% m                                                                ' u/ @2 Y: f1 O- y) s+ W
    解决方案:                                                               
) h; g) x. \4 L  u4 ]6 a. X* `                                                                我通常只插入和捕获DUP_VAL_ON_INDEX异常,因为这是最简单的代码。这比插入前检查是否存在更有效。我不认为这是难闻的气味(可怕的短语!),因为我们处理的异常是Oracle提出的-
( b6 ~9 E  Y+ N8 [1 m不像提出自己的异常作为流控机制。* X- x5 f* }) M6 o! a! I. {
感谢Igor我现在在这方面有两个不同的评论Benchamrk:(1)除第一次插入尝试外,所有插入尝试都是重复的;(2)所有插入都不是重复尝试。现实将介于这两种情况之间。/ ~& F+ a8 C8 v% x# W0 t4 \0 Q$ R
注意:在Oracle 10.2.0.3.0上执行的测试。
; E) q% `$ {! K情况1:大部分重复
4 n% ]) E* g: e0 w- V. |! Q' @) F最有效的方法是在插入时检查它是否存在:+ p( N' _- m7 ]
prompt 1) Check DUP_VAL_ON_INDEXbegin   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 insertingdeclare   dummy integer;begin   for i in 1..1000 loop      select count(*) into dummy      from hasviewed      where objectid=7782 and userid=二十、      if dummy = 0 then         insert into hasviewed values(7782,20);      end if;   end loop;   rollback;end;/prompt 3) Test if row exists while insertingbegin   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;/结果(运行一次以避免解析开销之后):
7 K) J0 W7 }$ V) r0 n1) Check DUP_VAL_ON_INDEXPL/SQL procedure successfully completed.Elapsed: 00:00:00.542) Test if row exists before insertingPL/SQL procedure successfully completed.Elapsed: 00:00:00.593) Test if row exists while insertingPL/SQL procedure successfully completed.Elapsed: 00:00:00.20情况二:无重复
3 o* P5 j+ g/ U0 nprompt 1) Check DUP_VAL_ON_INDEXbegin   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 insertingdeclare   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 insertingbegin   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) k$ }4 G7 e4 l; }: {6 s1) Check DUP_VAL_ON_INDEXPL/SQL procedure successfully completed.Elapsed: 00:00:00.152) Test if row exists before insertingPL/SQL procedure successfully completed.Elapsed: 00:00:00.763) Test if row exists while insertingPL/SQL procedure successfully completed.Elapsed: 00:00:00.71在这种情况下,DUP_VAL_ON_INDEX赢一英里。请注意,在两种情况下,插入前选择是最慢的。6 R- g5 m* L& I
因此,您似乎应该根据插入重复或不重复的相对可能性来选择选项1或3。
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则