JOB并行化
有些过程由于受限是单个JOB在跑,即使在表级别已经是并行化了,但是整个存储过程还是串行执行,而这时候资源又比较空闲,通过分而治之的方法,可以分多个并行JOB来执行,前提必须要对应用程序的行为比较了解,同时经过充分的测试.
1,新建一个表T1,插入一万条数据。
create table t1 (a int);
create table t2 (a int,b int);
declare
i int;
begin
for i in 1 .. 10000 loop
insert into t1 values (i);
end loop;
commit;
end;
2,现在假设有一个这样的test存储过程,对t1进行处理以后,结果往t2插入
create or replace procedure test is
begin
for i in (select a from t1) loop
insert into t2 values (i.a, sys_context('userenv', 'sessionid'));
end loop;
commit;
end;
SQL> exec test;
SQL> select b,count(*) from t2 group by b;
B COUNT(*)
--------------------------------------- ----------
4294967295 10000
可以看出由一个会话插入执行会部记录1万行
3,现在通过把t1分成10个小块,然后对test函数做一定的修改,可以通过并发会话来执行
create table t_temp as
select nt,min(rowid) minrowid,max(rowid) maxrowid
from
(select ntile(10) over (order by a) nt,a
from t1)
group by nt
order by nt
通过该分组函数把T1表分成十块,最好是表上的主键来进行分块
改写test存储过程
create or replace procedure test ( m in number)
is
j rowid;
k rowid;
begin
select minrowid,maxrowid into j,k from t_temp where nt=m;
for i in (select a from t1
where rowid between j and k )
loop
insert into t2 values (i.a,sys_context('userenv','sessionid'));
end loop;
commit;
end;
红色为增加的代码。可以看出改动的代码量并不大,如果过程代码更多,也只需要更改这么多的代码。
4,通过DBMS_JOB来调用新的存储过程
declare
j int;
begin
for i in (select nt from t_temp) loop
dbms_job.submit(j, 'test(' || i.nt || ');');
commit;
end loop;
end;
再查询一下,可以看到是通过十个分会话来分别insert了
SQL> select b,count(*) from t2 group by b;
B COUNT(*)
--------------------------------------- ----------
31762 1000
31758 1000
31763 1000
31756 1000
31759 1000
31757 1000
31754 1000
31755 1000
31760 1000
31761 1000
10 rows selected
当我在测试10亿条数据insert的时候,效果非常明显。可以看出达到我们期望的并发效果。总结一下:1,对应用要十分了解;2,充分的测试;3,服务器有充分的资源。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/22749436/viewspace-753489/ ,如需转载,请注明出处,否则将追究法律责任。