【发布时间】:2016-05-20 19:06:34
【问题描述】:
我需要通过存储过程处理 Oracle 表的近 60k 条记录。处理过程是,对于每一个这样的行,我需要在第二个表中删除和更新一行,并在第三个表中插入一行。
使用光标循环,该过程大约需要 6-8 小时才能完成。如果我切换到带限制的批量收集,执行时间会减少但处理不正确。以下是程序的批量收集版本
create or replace procedure myproc()
is
cursor c1 is select col1,col2,col3 from tab1 where col4=3;
type t1 is table of c1%rowtype;
v_t1 t1;
begin
open c1;
loop
fetch c1 bulk collect into v_t1 limit 1000;
exit when v_t1.count=0;
forall i in 1..v_t1.count
delete from tab2 where tab2.col1=v_t1(i).col1;
commit;
forall i in 1..v_t1.count
update tab2 set tab2.col1=v_t1(i).col1 where tab2.col2=v_t1(i).col2;
commit;
forall i in 1..v_t1.count
insert into tab3 values(v_t1(i).col1,v_t1(i).col2,v_t1(i).col3);
commit;
end loop;
close c2;
end;
对于这些记录中的大约 20k,第一次删除操作被正确处理,但后续更新和插入未处理。对于剩余的 40k 条记录,所有三个操作都已正确处理。
我错过了什么吗?另外,我可以对 Bulk Collect 使用的最大 LIMIT 值是多少?
【问题讨论】:
-
所以你知道你在主循环上迭代了 60 次,你知道你做了 60k 删除但 40k 更新和插入?你是如何检查/计数的?
-
表tab3是一个日志表,在执行过程之前被清除;因此,如果在执行该过程后该表中有 40k 条记录,则意味着 40k 插入成功。表(tab1)在执行过程之前有接近 2*60k 的记录,执行之后,记录计数为 60k,这意味着 60k 删除成功。
-
好的,tab2.col1 是唯一的吗?我不是想变得困难,只是想想想你可能忽略了什么。
-
是的,这是独一无二的,而且是一个具体的数字。
标签: oracle plsql cursor forall bulk-collect