Tôi thường chỉ chèn và bẫy ngoại lệ DUP_VAL_ON_INDEX, vì đây là mã đơn giản nhất. Điều này hiệu quả hơn việc kiểm tra sự tồn tại trước khi chèn. Tôi không coi việc làm này là "mùi khó chịu" (cụm từ kinh khủng!) Vì trường hợp ngoại lệ mà chúng tôi xử lý là do Oracle nêu ra - nó không giống như việc nâng cao các ngoại lệ của riêng bạn như một cơ chế kiểm soát luồng.
Nhờ nhận xét của Igor, tôi đã chạy hai benchamrks khác nhau về vấn đề này:(1) trong đó tất cả các lần chèn ngoại trừ lần đầu tiên là trùng lặp, (2) trong đó tất cả các lần chèn không trùng lặp. Thực tế sẽ nằm ở đâu đó giữa hai trường hợp.
Lưu ý:các bài kiểm tra được thực hiện trên Oracle 10.2.0.3.0.
Trường hợp 1:Chủ yếu là trùng lặp
Có vẻ như cách tiếp cận hiệu quả nhất (bởi một yếu tố quan trọng) là kiểm tra sự tồn tại của việc chèn WHILE:
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;
/
Kết quả (sau khi chạy một lần để tránh chi phí phân tích cú pháp):
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
Trường hợp 2:không có bản sao
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;
/
Kết quả:
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
Trong trường hợp này, DUP_VAL_ON_INDEX thắng một dặm. Lưu ý rằng "chọn trước khi chèn" là chậm nhất trong cả hai trường hợp.
Vì vậy, có vẻ như bạn nên chọn tùy chọn 1 hoặc 3 tùy theo khả năng tương đối của các phần chèn có bị trùng lặp hay không.