PLSQL批量Forall操作性能提升详解
--事实证明,使用bulk操作对比普通单条执行来说,不光是可以减少plsql与sql引擎之间的频繁切换。还可以减少redo与undo的生成。--
首先创建测试表
create table test1 (c1 number , c2 number ,c3 number) ;
create table test2 (c1 number , c2 number ,c3 number) ;
开始测试
SQL> declare
2
2 l_stat_sql varchar2(2000) := 'select value from v$mystat ms, v$statname sn where ms.STATISTIC# = sn.STATISTIC# and name = :1 ';
3 type t is table of test2%rowtype ;
4 l t := t() ;
5 l_undo_stat1 int;
6 l_undo_stat2 int;
7 l_undo_stat3 int;
8 l_redo_stat1 int;
9 l_redo_stat2 int;
10 l_redo_stat3 int;
11 l_time_stat1 int;
12 l_time_stat2 int;
13 l_time_stat3 int;
14 begin
15 l_time_stat1 := dbms_utility.get_time ;
16 execute immediate l_stat_sql into l_redo_stat1 using 'redo size';
17 execute immediate l_stat_sql into l_undo_stat1 using 'undo change vector size';
18 for i in 1 .. 10000 loop
19 insert into test1 values(i,i/2,mod(i,2)) ;
20 end loop ;
21 l_time_stat2 := dbms_utility.get_time ;
22 execute immediate l_stat_sql into l_redo_stat2 using 'redo size';
23 execute immediate l_stat_sql into l_undo_stat2 using 'undo change vector size';
24 l.extend(10000) ;
25 for i in 1 .. 10000 loop
26 l(i).c1 := i ;
27 l(i).c2 := i/2 ;
28 l(i).c3 := mod(i,2) ;
29 end loop;
30 forall i in 1 .. l.last
31 insert into test2 values l(i) ;
32 l_time_stat3 := dbms_utility.get_time ;
33 execute immediate l_stat_sql into l_redo_stat3 using 'redo size';
34 execute immediate l_stat_sql into l_undo_stat3 using 'undo change vector size';
35
36 dbms_output.put_line('OneByOne redo : ' || (l_redo_stat2-l_redo_stat1) ) ;
37 dbms_output.put_line('Bulk redo : ' || (l_redo_stat3-l_redo_stat2) ) ;
38 dbms_output.put_line('-') ;
39 dbms_output.put_line('OneByOne undo : ' || (l_undo_stat2-l_undo_stat1) ) ;
40 dbms_output.put_line('Bulk undo : ' || (l_undo_stat3-l_undo_stat2) ) ;
41 dbms_output.put_line('-') ;
42 dbms_output.put_line('OneByOne time : ' || (l_time_stat2-l_time_stat1) ) ;
43 dbms_output.put_line('Bulk time : ' || (l_time_stat3-l_time_stat2) ) ;
44 end;
45 /
OneByOne redo : 2582244
Bulk redo : 228428
-
OneByOne undo : 681172
Bulk undo : 25432
-
OneByOne time : 84
Bulk time : 2
PL/SQL procedure successfully completed
--事实证明,使用bulk操作对比普通单条执行来说,不光是可以减少plsql与sql引擎之间的频繁切换。还可以减少redo与undo的生成。
--可以看到redo 相差10倍,undo相差将近20倍。
--时间上来说单条执行使用了840毫秒,,而批量模式则只使用了20毫秒,差距不可说不大。
因为实在同一个事务中,所以scn号相同
SQL> select ora_rowscn ,t.* from test1 t where rownum
ORA_ROWSCN C1 C2 C3
---------- ---------- ---------- ----------
17108596 2289 1144.5 1
17108596 2290 1145 0
17108596 2291 1145.5 1
17108596 2292 1146 0
17108596 2293 1146.5 1
17108596 2294 1147 0
17108596 2295 1147.5 1
17108596 2296 1148 0
17108596 2297 1148.5 1
17108596 2298 1149 0
10 rows selected
SQL> select ora_rowscn ,t.* from test2 t where rownum
ORA_ROWSCN C1 C2 C3
---------- ---------- ---------- ----------
17108596 2289 1144.5 1
17108596 2290 1145 0
17108596 2291 1145.5 1
17108596 2292 1146 0
17108596 2293 1146.5 1
17108596 2294 1147 0
17108596 2295 1147.5 1
17108596 2296 1148 0
17108596 2297 1148.5 1
17108596 2298 1149 0
10 rows selected