11g包dbms_parallel_execute在海量数据处理过程中的应用

  1. 云栖社区>
  2. 博客>
  3. 正文

11g包dbms_parallel_execute在海量数据处理过程中的应用

流浪的猫666 2018-08-19 11:09:29 浏览1506
展开阅读全文

查看环境版本
select * from v$version;
1 Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production 0
2 PL/SQL Release 12.2.0.1.0 - Production 0
3 "CORE 12.2.0.1.0 Production" 0
4 TNS for 64-bit Windows: Version 12.2.0.1.0 - Production 0
5 NLSRTL Version 12.2.0.1.0 - Production 0
第一步:

Oracle生成100万条测试数据的方法

Oracle生成一百万测试数据的方法如下:

方法一:创建一个表,并同时添加1000000条数据,代码:

create table TestTable as
select rownum as id,

           to_char(sysdate + rownum/24/3600, 'yyyy-mm-dd hh24:mi:ss') as inc_datetime,
           trunc(dbms_random.value(0, 100)) as random_id,
           dbms_random.string('x', 20) random_string
      from dual
    connect by level <= 1000000;
    

方法二:在创建表后,原来表的基础上追加记录,比如在方法一创建的TestTable表中追加1000000条数据,代码:

insert into TestTable
(ID, INC_DATETIME,RANDOM_ID,RANDOM_STRING)
select rownum as id,

     to_char(sysdate + rownum / 24 / 3600, 'yyyy-mm-dd hh24:mi:ss') as inc_datetime,
     trunc(dbms_random.value(0, 100)) as random_id,
     dbms_random.string('x', 20) random_string
from dual

connect by level <= 1000000;

上面SQL是利用了Oracle数据库语法的几个实用小技巧实现的:
1、利用Oracle特有的“connect by”树形连接语法生成测试记录,“level <= 10”表示要生成10记录;
2、利用rownum虚拟列生成递增的整数数据;
3、利用sysdate函数加一些简单运算来生成日期数据,本例中是每条记录的时间加1秒;
4、利用dbms_random.value函数生成随机的数值型数据,本例中是生成0到100之间的随机整数;
5、利用dbms_random.string函数生成随机的字符型数据,本例中是生成长度为20的随机字符串,字符串中可以包括字符或数字。

第二步:

Oracle11.2新特性之使用DBMS_PARALLEL_EXECUTE包实现并行
使用DBMS_PARALLEL_EXECUTE包实现并行
比如现在有一个表 t 有1000万行,如果想以这个表为基础,把数据选择性的插入另外一个表t2,
使用Insert into TestTable_tmpd select *from TestTable_tmp;
使用并行来处理也没有问题,但是如果使用dbms_parallel_execute也是一种很不错的选择。
使用dbms_parallel_execute的实现方式和parallel还有一定的差别。
这个包在11g开始引入,可能初次接触的时候会被它大量的功能所淹没,不知道从何开始。
该包支持insert、update、delete、merge、匿名包自动以scheduler job 方式并行执行。
支持的chunk方式包括:
CREATE_CHUNKS_BY_NUMBER_COL Procedure
CREATE_CHUNKS_BY_ROWID Procedure
CREATE_CHUNKS_BY_SQL Procedure

create table TestTable_tmpd as select * from TestTable_tmp where 1=2;
select * from TestTable_tmpd;

使用如下的存储过程来模拟一个dml的处理过程。传入的参数,是根据rowid来处理。
create or replace procedure serial(p_lo_rid in rowid,p_hi_rid in rowid)
is
begin
for x in (select id,inc_datetime,random_id,random_string from TestTable_tmp where rowid between p_lo_rid and p_hi_rid)
loop
insert into TestTable_tmpd(id,inc_datetime,random_id,random_string)
values(x.id,x.inc_datetime,x.random_id,x.random_string);
end loop;
end;
使用dbms_parallel_execute来创建一个Job,以1万条数据分单位进行数据的rowid切分。

begin
dbms_parallel_execute.create_task('PROCESS TASK');
dbms_parallel_execute.create_chunks_by_rowid
( task_name=>'PROCESS TASK',
table_owner=>'C##TEST',
table_name=>'TESTTABLE_TMP',
by_row=>false,
chunk_size=>100000);
end;

通过dba_parallel_execute_chunks可以查看到切分后的rowid情况。

set pages 200
select *from (
select chunk_id,status,start_rowid,end_rowid
from dba_parallel_execute_chunks
where task_name='PROCESS TASK'
order by chunk_id
);

查看切分后的情况,我们可以把切分后的每一个子块称为chunk。可以通过这个语句来简单的监控进度。

1 8 UNASSIGNED AAASQ4AAMAAAR4wAAA AAASQ4AAMAAAT5/H//

可以使用如下的部分来开始处理数据。启用了4个并行,并行度可以情况来提高。:start_id,:end_id是上面对应的rowid.

可以使用如下的部分来开始处理数据。启用了4个并行,并行度可以情况来提高。:start_id,:end_id是上面对应的rowid.

begin
dbms_parallel_execute.run_task
(task_name=>'PROCESS TASK',
sql_stmt=>'begin serial(:start_id,:end_id); end;',
language_flag=>DBMS_SQL.NATIVE,
parallel_level=>4);
end;
/
处理完数据之后,就可以删除这个job了。

begin
dbms_parallel_execute.drop_task('PROCESS TASK');
end;

在数据处理的时候。可以看到dbms_parallel_execute后台启用的处理进程和并行还是有一些不同的。
启用了4个并行之后,看到都是j00这样的进程

网友评论

登录后评论
0/500
评论
流浪的猫666
+ 关注