使用dbms_parallel_execute来完成DML的并行(r3笔记第1天)
在工作中使用并行可以极大的提高工作效率。可以Object,session.hint级别引入并行。可以使大量的数据处理更加高效。 比如现在有一个表 t 有1000万行,如果想以这个表为基础,把数据选择性的插入另外一个表t2, 使用Insert into t2 select *from t; 使用并行来处理也没有问题,但是如果使用dbms_parallel_execute也是一种很不错的选择。 使用dbms_parallel_execute的实现方式和parallel还有一定的差别。 这个包在11g开始引入,可能初次接触的时候会被它大量的功能所淹没,不知道从何开始。 举个例子来说明一下。 我们创建一个表 t,限于环境的情况,目前做一个百万级别的数据dml操作,使用dbms_parallel_execute来完成。 创建表t.
SQL> drop table t;
Table dropped.
SQL> create table t as select object_id,object_name from dba_objects;
Table created.
创建表t2,我们专门专门多加了一个字段。session_id。到时候会有用处。
SQL> drop table t2;
Table dropped.
SQL> create table t2 as select t1.*,0 session_id from t t1 where 1=0;
Table created.
使用如下的存储过程来模拟一个dml的处理过程。传入的参数,是根据rowid来处理。
create or replace procedure serial(p_lo_rid in rowid,p_hi_rid in rowid)
is
begin
for x in (select object_id object_id,object_name object_name from t where rowid between p_lo_rid and p_hi_rid)
loop
insert into t2(object_id,object_name,session_id)
values(x.object_id,x.object_name,sys_context('userenv','sessionid'));
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=>user,
table_name=>'T',
by_row=>false,
chunk_size=>10000);
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。可以通过这个语句来简单的监控进度。
CHUNK_ID STATUS START_ROWID END_ROWID
---------- -------------------- ------------------ ------------------
600 UNASSIGNED AAAEQCAAFAAAACAAAA AAAEQCAAFAAAAD/CcP
601 UNASSIGNED AAAEQCAAFAAAAEAAAA AAAEQCAAFAAAAF/CcP
602 UNASSIGNED AAAEQCAAFAAAAGAAAA AAAEQCAAFAAAAH/CcP
603 UNASSIGNED AAAEQCAAFAAAAIAAAA AAAEQCAAFAAAAJ/CcP
604 UNASSIGNED AAAEQCAAFAAAAKAAAA AAAEQCAAFAAAAL/CcP
605 UNASSIGNED AAAEQCAAFAAAAWAAAA AAAEQCAAFAAAAX/CcP
606 UNASSIGNED AAAEQCAAFAAAAYAAAA AAAEQCAAFAAAAZ/CcP
607 UNASSIGNED AAAEQCAAFAAAAaAAAA AAAEQCAAFAAAAb/CcP
608 UNASSIGNED AAAEQCAAFAAAAcAAAA AAAEQCAAFAAAAd/CcP
609 UNASSIGNED AAAEQCAAFAAAEsYAAA AAAEQCAAFAAAEsfCcP
610 UNASSIGNED AAAEQCAAFAAAEsgAAA AAAEQCAAFAAAEsnCcP
可以使用如下的部分来开始处理数据。启用了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;
/
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_ID STATUS START_ROWID END_ROWID
---------- -------------------- ------------------ ------------------
600 PROCESSED AAAEQCAAFAAAACAAAA AAAEQCAAFAAAAD/CcP
601 PROCESSED AAAEQCAAFAAAAEAAAA AAAEQCAAFAAAAF/CcP
602 PROCESSED AAAEQCAAFAAAAGAAAA AAAEQCAAFAAAAH/CcP
603 PROCESSED AAAEQCAAFAAAAIAAAA AAAEQCAAFAAAAJ/CcP
604 PROCESSED AAAEQCAAFAAAAKAAAA AAAEQCAAFAAAAL/CcP
605 PROCESSED AAAEQCAAFAAAAWAAAA AAAEQCAAFAAAAX/CcP
606 PROCESSED AAAEQCAAFAAAAYAAAA AAAEQCAAFAAAAZ/CcP
607 PROCESSED AAAEQCAAFAAAAaAAAA AAAEQCAAFAAAAb/CcP
608 PROCESSED AAAEQCAAFAAAAcAAAA AAAEQCAAFAAAAd/CcP
处理完数据之后,就可以删除这个job了。
begin
dbms_parallel_execute.drop_task('PROCESS TASK');
end;
/
我们可以在t2的新增列中看到每个对应的parallel处理的数据情况,可以看到数据的处理还是很平均的。
select session_id,count(*)
from t2
group by session_id
order by session_id;
SESSION_ID COUNT(*)
---------- ----------
1670371 357834
1670372 370487
1670373 403604
1670374 404679
在数据处理的时候。可以看到dbms_parallel_execute后台启用的处理进程和并行还是有一些不同的。
启用了4个并行之后,看到都是j00这样的进程。
top - 06:31:03 up 1 day, 5:21, 2 users, load average: 3.97, 1.55, 0.61
Tasks: 167 total, 4 running, 163 sleeping, 0 stopped, 0 zombie
Cpu(s): 60.7%us, 7.7%sy, 0.0%ni, 1.0%id, 28.9%wa, 0.2%hi, 1.5%si, 0.0%st
Mem: 2030124k total, 1293220k used, 736904k free, 358400k buffers
Swap: 4063224k total, 0k used, 4063224k free, 476552k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
32630 ora11g 20 0 530m 67m 64m D 55.2 3.4 0:48.34 ora_j000_TEST01
32634 ora11g 20 0 529m 60m 57m R 38.4 3.0 0:46.88 ora_j002_TEST01
32632 ora11g 20 0 529m 62m 59m R 24.8 3.2 0:44.54 ora_j001_TEST01
32636 ora11g 20 0 529m 59m 56m R 17.5 3.0 0:44.88 ora_j003_TEST01
2295 ora11g 20 0 541m 79m 67m D 1.3 4.0 0:11.93 ora_dbw0_TEST01
32706 ora11g 20 0 14940 1240 904 R 1.0 0.1 0:00.39 top -c
825 root 20 0 0 0 0 S 0.3 0.0 0:18.85 [jbd2/sdb3-8]
如果调高parallel从4到16,可以看到j00的进程相应的增加了。
top - 06:32:59 up 1 day, 5:23, 2 users, load average: 1.31, 1.29, 0.63
Tasks: 182 total, 4 running, 178 sleeping, 0 stopped, 0 zombie
Cpu(s): 77.2%us, 21.2%sy, 0.0%ni, 1.2%id, 0.2%wa, 0.0%hi, 0.2%si, 0.0%st
Mem: 2030124k total, 1345284k used, 684840k free, 358500k buffers
Swap: 4063224k total, 0k used, 4063224k free, 476800k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
404 ora11g 20 0 530m 39m 36m R 23.4 2.0 0:01.75 ora_j010_TEST01
392 ora11g 20 0 529m 33m 30m S 17.1 1.7 0:01.39 ora_j004_TEST01
402 ora11g 20 0 529m 31m 28m R 16.1 1.6 0:00.86 ora_j009_TEST01
384 ora11g 20 0 530m 35m 32m S 12.2 1.8 0:01.21 ora_j000_TEST01
386 ora11g 20 0 529m 32m 29m S 11.9 1.6 0:01.11 ora_j001_TEST01
422 root 20 0 122m 19m 10m S 11.5 1.0 0:00.35 /u04/app/11.2.0/grid/bin/crsctl.bin check has
394 ora11g 20 0 529m 31m 29m S 10.5 1.6 0:00.86 ora_j005_TEST01
410 ora11g 20 0 530m 31m 28m R 10.5 1.6 0:00.63 ora_j013_TEST01
408 ora11g 20 0 529m 32m 29m S 9.6 1.6 0:00.93 ora_j012_TEST01
388 ora11g 20 0 529m 32m 29m S 8.9 1.6 0:01.14 ora_j002_TEST01
398 ora11g 20 0 530m 32m 29m S 8.6 1.6 0:00.98 ora_j007_TEST01
390 ora11g 20 0 529m 31m 28m S 7.6 1.6 0:00.74 ora_j003_TEST01
396 ora11g 20 0 529m 32m 29m S 7.2 1.6 0:01.04 ora_j006_TEST01
406 ora11g 20 0 530m 30m 27m S 5.6 1.5 0:00.49 ora_j011_TEST01
414 ora11g 20 0 529m 29m 26m S 5.6 1.5 0:00.45 ora_j015_TEST01
400 ora11g 20 0 529m 30m 27m S 4.9 1.5 0:00.64 ora_j008_TEST01
412 ora11g 20 0 530m 30m 27m S 4.6 1.5 0:00.63 ora_j014_TEST01
- web调试工具——Fiddler使用介绍(一)
- Windows c++应用程序通用日志组件(组件及测试程序下载)
- 快速排序
- 如何在Elasticsearch中安装中文分词器(IK+pinyin)
- Python抓取中文网页
- 《Effective Java》—— 读后总结
- unix共享内存要点
- LAMP=Linux+Apache+Mysql+Php
- unix共享内存要点
- Elasticsearch —— bulk批量导入数据
- 自己写的数据交换工具——从Oracle到Elasticsearch
- PHP程序员应该掌握的10个技能
- Elasticsearch查询——布尔查询Bool Query
- 合并排序
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一天一大 lee(最短回文串)难度:困难-Day20200829
- 一天一大 lee(预测赢家)难度:中等-Day20200901
- 一天一大 lee(反转字符串中的单词 III)难度:简单-Day20200830
- 一天一大 lee(平衡二叉树)难度:简单-Day20200817
- 一天一大 lee(组合总和)难度:中等-Day20200909
- 一天一大 lee(回文子串)难度:中等-Day20200819
- 一天一大 lee(组合)难度:中等-Day20200908
- es6学习笔记
- 一天一大 lee(图像渲染)难度:简单-Day20200816
- 一天一大 lee(前 K 个高频元素)难度:中等-Day20200907
- 一天一大 lee(二叉树的层次遍历 II)难度:简单-Day20200906
- 一天一大 lee(第k个排列)难度:中等-Day20200905
- 一天一大 lee(二叉树的所有路径)难度:简单-Day20200904
- 一天一大 lee(N 皇后)难度:困难-Day20200903
- 一天一大 lee(二叉树的中序遍历)难度:中等-Day20200914