oracle 批处理 bulk collect 带来的性能优势

create table

-- drop table tmp_20190706_220000
-- truncate table tmp_20190706_220000

create table tmp_20190706_220000 (
id integer,
name varchar(100),
memo varchar(200)
)
;


1
2
3
4
5
6
7
8
9
10
11
plsql into

通常简单的写法如下

declare
lv_id tmp_20190706_220000.id%type;
lv_name tmp_20190706_220000.name%type;
lv_memo tmp_20190706_220000.memo%type;

lv_sql varchar2(4000);
cur_tmp sys_refcursor;

begin
lv_sql:='select id,name,memo from tmp_20190704_220000 ';
open cur_tmp for lv_sql;
loop
fetch cur_tmp into lv_id,lv_name,lv_memo ;

exit when cur_tmp%notfound;

end loop;

close cur_tmp;

if cur_tmp%isopen then
close cur_tmp;
end if;

end;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
消耗时长


plsql bulk collect into

bulk collect 的写法如下

declare
type type_tmp_id is table of tmp_20190706_220000.id%TYPE index by pls_integer;
type type_tmp_name is table of tmp_20190706_220000.name%TYPE index by pls_integer;
type type_tmp_memo is table of tmp_20190706_220000.memo%TYPE index by pls_integer;

lv_id type_tmp_id;
lv_name type_tmp_name;
lv_memo type_tmp_memo;

lv_sql varchar2(4000);
cur_tmp sys_refcursor;

CN_BATCH_SIZE constant pls_integer :=100000;

begin
lv_sql:='select id,name,memo from tmp_20190704_220000 ';
open cur_tmp for lv_sql;
loop
fetch cur_tmp bulk collect into lv_id,lv_name,lv_memo limit CN_BATCH_SIZE;

exit when lv_id.count < CN_BATCH_SIZE;

end loop;

close cur_tmp;

if cur_tmp%isopen then
close cur_tmp;
end if;

end;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
消耗时长


差异还是蛮大的。

plsql into & insert into

declare
lv_id tmp_20190706_220000.id%type;
lv_name tmp_20190706_220000.name%type;
lv_memo tmp_20190706_220000.memo%type;

lv_sql varchar2(4000);
cur_tmp sys_refcursor;

begin
lv_sql:='select id,name,memo from tmp_20190704_220000 ';
open cur_tmp for lv_sql;
loop
fetch cur_tmp into lv_id,lv_name,lv_memo ;
insert into tmp_20190706_220000
( id,
name,
memo
)
values(
lv_id,
lv_name,
lv_memo
)
;
exit when cur_tmp%notfound;

end loop;

commit;
close cur_tmp;

if cur_tmp%isopen then
close cur_tmp;
end if;

end;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
消耗时长


plsql bulk collect into & insert into

declare
type type_tmp_id is table of tmp_20190706_220000.id%TYPE index by pls_integer;
type type_tmp_name is table of tmp_20190706_220000.name%TYPE index by pls_integer;
type type_tmp_memo is table of tmp_20190706_220000.memo%TYPE index by pls_integer;

lv_id type_tmp_id;
lv_name type_tmp_name;
lv_memo type_tmp_memo;

lv_sql varchar2(4000);
cur_tmp sys_refcursor;

CN_BATCH_SIZE constant pls_integer :=100000;

begin
lv_sql:='select id,name,memo from tmp_20190704_220000 ';
open cur_tmp for lv_sql;
loop
fetch cur_tmp bulk collect into lv_id,lv_name,lv_memo limit CN_BATCH_SIZE;
forall c_k in lv_id.FIRST .. lv_id.LAST
insert into tmp_20190706_220000(
id,
name,
memo
)
values (
lv_id(c_k),
lv_name(c_k),
lv_memo(c_k)
)
;
commit;

exit when lv_id.count < CN_BATCH_SIZE;

end loop;

close cur_tmp;

if cur_tmp%isopen then
close cur_tmp;
end if;

end;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
消耗时长

使用 bulk collect 和 forall 性能均有大幅度提高。
---------------------

原文地址:https://www.cnblogs.com/ly570/p/11161462.html