Oracle Bulk collect 和 forall语法

概述:  

  在处理一个大约有400W数据的表中的冗余数据,使用cursor来一条一条处理的时候,发现耗时大约为5 hours左右。之后采用Oracle提供的BULK COLLECT和FORALL改写程序,耗时降到1个小时左右,速度提高了5倍左右。原因是:

  1. 使用BLUK COLLECT一次取出一个数据集合,比用游标条取数据效率高,尤其是在网络不大好的情况下。但BLUK COLLECT需要大量内存。
  2. 使用FORALL比FOR效率高,因为前者只切换一次上下文,而后者将是在循环次数一样多个上下文间切换。


语法:

1. select into中使用bulk collect

 SELECT id, code BULK COLLECT INTO v_table;

2. fetch into中使用bulk collect

    fetch cursor1 BULK COLLECT INTO v_table;

3. returning into中使用bulk collect
    DELETE FROM table1 WHERE id = 1 RETURNING id, code BULK COLLECT INTO v_table;
4. 批量更新中,使用forall而不是FOR 

1 DECLARE
2 TYPE NumList IS VARRAY(20) OF NUMBER;
3   depts NumList := NumList(10, 30, 70);
4 BEGIN
5   FOR i IN depts.FIRST .. depts.LAST LOOP
6    UPDATE t_test SET sal = sal * 1.10 WHERE deptno = depts(i);
7   END LOOP;
8 END;

改用FORALL后:

1 DECLARE
2 TYPE NumList IS VARRAY(20) OF NUMBER;
3 depts NumList := NumList(10, 30, 70);
4 BEGIN
5 FORALL i IN depts.FIRST..depts.LAST
6 UPDATE emp SET sal = sal * 1.10 WHERE deptno = depts(i);
7 END;


完整语法示例:

 1 declare
2 TYPE REL IS RECORD(
3 id T_REL.id%TYPE,
4 code T_REL.code%TYPE,
5 );
6
7 TYPE TABLE_REL IS TABLE OF REL INDEX BY BINARY_INTEGER;
8 var_rel TABLE_REL;
9
10 cursor cur_MAX_REL is
11 SELECT max(id) as id
12 FROM T_REL
13 GROUP BY code;
14
15 begin
16 open cur_MAX_REL;
17 loop
18 FETCH cur_MAX_REL BULK COLLECT
19 INTO var_rel LIMIT 10000;
20
21 FORALL i IN var_rel.FIRST .. var_rel.LAST
22 insert into t_test
23 (id, code)
24 values var_rel(i);
25
26 exit when cur_MAX_REL%NOTFOUND;
27 end loop;
28 close cur_MAX_REL;
29 commit;
30 EXCEPTION
31 WHEN OTHERS THEN
32 IF cur_MAX_REL%ISOPEN THEN
33 CLOSE cur_MAX_REL;
34 END IF;
35 dbms_output.put_line(chr(10) || sqlerrm);
36 END;
posted @ 2012-04-06 17:23  先行而后三思  阅读(1298)  评论(0编辑  收藏  举报