-----------------------------Cryking原创------------------------------
-----------------------转载请注明出处,谢谢!------------------------

并行处理能大大提高数据的处理速度,它依赖于硬件资源、网络资源等环境.

并行处理的硬件资源环境分为5大类:

1.传统的单台计算机、单处理器、单内核的机器.(无法进行并行处理,但是并行程序还是可以运行的,此时就和普通程序一样了)

2.单台计算机、单处理器、多内核的机器.(目前本人的测试环境,没钱买多处理器的)

3.单台计算机、多处理器、多内核的机器.

4.集群系统

5.分布式系统

PS:如何查看几个处理器、几核,常用的软件就是CPU-Z.

本人的测试机器CPU:

单CPU,双核心处理器

下面开始,编写一个普通的管道函数(这里演示的就是管道函数的并行处理):

CREATE OR REPLACE FUNCTION pipe_test
(
c_empno SYS_REFCURSOR
,p VARCHAR2 DEFAULT ','
) RETURN EMP_element
PIPELINED IS
v_element VARCHAR2(1000);
BEGIN
FETCH c_empno
INTO v_element;
LOOP
EXIT WHEN c_empno%NOTFOUND;
PIPE ROW(substr(v_element, 0, instr(v_element, p) - 1));
LOOP
v_element := substr(v_element
,instr(v_element, p) + 1
,length(v_element) - instr(v_element, p) + 1);
EXIT WHEN instr(v_element, p) = 0;
PIPE ROW(substr(v_element, 0, instr(v_element, p) - 1));
END LOOP;
PIPE ROW(v_element);
FETCH c_empno
INTO v_element;
END LOOP;
RETURN;
END pipe_test;

注意需要先建立类型EMP_element,如下:

CREATE OR REPLACE TYPE EMP_element as table of varchar2(100);

然后我们建立一个并行处理的管道函数:

CREATE OR REPLACE FUNCTION parallel_test
(
p_empno SYS_REFCURSOR
,p VARCHAR2 DEFAULT ','
) RETURN EMP_element
PIPELINED
PARALLEL_ENABLE(PARTITION p_empno BY ANY) IS
v_element VARCHAR2(1000);
BEGIN
FETCH p_empno
INTO v_element;
LOOP
EXIT WHEN p_empno%NOTFOUND;
PIPE ROW(substr(v_element, 0, instr(v_element, p) - 1));
LOOP
v_element := substr(v_element
,instr(v_element, p) + 1
,length(v_element) - instr(v_element, p) + 1);
EXIT WHEN instr(v_element, p) = 0;
PIPE ROW(substr(v_element, 0, instr(v_element, p) - 1));
END LOOP;
PIPE ROW(v_element);
FETCH p_empno
INTO v_element;
END LOOP;
RETURN;
END parallel_test;

留意下启用并行的关键字PARALLEL_ENABLE.

接下来我们构造大表进行测试,根据v$pq_sesstat视图的结果,我们来判断数据库系统是否真的进行了并行处理.

12:57:52 SYS@orcl> create table big_data as select 'Cc' a,'Dd' b from dual connect by level<1000000;

表已创建。

已用时间:  00: 00: 01.92
12:59:00 SYS@orcl> select count(*) from big_data; COUNT(*)
----------
999999 已选择 1 行。 已用时间: 00: 00: 00.31
13:47:08 SYS@orcl> set autot trace exp stat
--普通管道函数耗时40.48秒
13:48:42 SYS@orcl> select SCOTT.pipe_test(CURSOR(SELECT a||','||b from big_data)) FROM DUAL; 已选择 1 行。 已用时间: 00: 00: 40.48 执行计划
----------------------------------------------------------
Plan hash value: 2452824241 ------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 (0)| 00:00:01 |
| 1 | VIEW | | 8168 | 414K| 29 (0)| 00:00:01 |
| 2 | COLLECTION ITERATOR PICKLER FETCH| PIPE_TEST | 8168 | | 29 (0)| 00:00:01 |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------ Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
1000515 recursive calls
0 db block gets
1000325 consistent gets
1548 physical reads
0 redo size
6027769 bytes sent via SQL*Net to client
1214 bytes received via SQL*Net from client
10 SQL*Net roundtrips to/from client
7 sorts (memory)
0 sorts (disk)
1 rows processed 13:53:24 SYS@orcl> alter system flush shared_pool; 系统已更改。 已用时间: 00: 00: 01.43
--使用启用并行的管道函数,耗时40.32,与普通的管道函数耗时差不多
--奇怪的是执行计划了多了一个BIG_DATA的全表扫描操作了
13:53:26 SYS@orcl> select SCOTT.parallel_test(CURSOR(SELECT a||','||b from big_data)) FROM DUAL; 已选择 1 行。 已用时间: 00: 00: 40.32 执行计划
----------------------------------------------------------
Plan hash value: 1682567826 ---------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | ---------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 2 (0)| 00:00:01 | | 1 | VIEW | | 8168 | 414K| 29 (0)| 00:00:01 | | 2 | COLLECTION ITERATOR PICKLER FETCH| PARALLEL_TEST | 8168 | | 29 (0)| 00:00:01 | | 3 | TABLE ACCESS FULL | BIG_DATA | 968K| 7565K| 422 (3)| 00:00:06 | | 4 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | ---------------------------------------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2) 统计信息
----------------------------------------------------------
1000867 recursive calls
0 db block gets
1000353 consistent gets
1560 physical reads
0 redo size
6026847 bytes sent via SQL*Net to client
1006 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
9 sorts (memory)
0 sorts (disk)
1 rows processed
--通过v$pq_sesstat视图我们发现此时系统并没有进行并行处理,(其实通过执行计划也可看出没有使用并行)
13:54:21 SYS@orcl> select * from v$pq_sesstat; STATISTIC LAST_QUERY SESSION_TOTAL
------------------------------ ---------- -------------
Queries Parallelized 0 0
DML Parallelized 0 0
DDL Parallelized 0 0
DFO Trees 0 0
Server Threads 0 0
Allocation Height 0 0
Allocation Width 0 0
Local Msgs Sent 0 0
Distr Msgs Sent 0 0
Local Msgs Recv'd 0 0
Distr Msgs Recv'd 0 0 已选择11行。 已用时间: 00: 00: 00.00 13:54:40 SYS@orcl> alter system flush buffer_cache; 系统已更改。 已用时间: 00: 00: 00.00
13:55:27 SYS@orcl> alter system flush shared_pool; 系统已更改。 已用时间: 00: 00: 01.40
--接下来我们加HINT,强制并行处理,此时耗时25.03秒,降低了一半
13:55:30 SYS@orcl> select /*+ parallel */scott.PARALLEL_TEST(CURSOR(SELECT a||','||b from big_data))
FROM DUAL; 已选择 1 行。 已用时间: 00: 00: 25.03 执行计划
----------------------------------------------------------
Plan hash value: 3127237831 ----------------------------------------------------------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib | ----------------------------------------------------------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 1 | | 2 (0)| 00:00:01 | | | | | 1 | PX COORDINATOR | | | | | | | | | | 2 | PX SEND QC (RANDOM) | :TQ10000 | 8168 | 414K| 16 (0)| 00:00:01 | Q1,00 | P->S | QC (RAND) | | 3 | VIEW | | 8168 | 414K| 16 (0)| 00:00:01 | Q1,00 | PCWP | | | 4 | COLLECTION ITERATOR PICKLER FETCH| PARALLEL_TEST | 8168 | | 16 (0)| 00:00:01 | Q1,00 | PCWP | | | 5 | PX BLOCK ITERATOR | | 968K| 7565K| 234 (3)| 00:00:03 | Q1,00 | PCWC | | | 6 | TABLE ACCESS FULL | BIG_DATA | 968K| 7565K| 234 (3)| 00:00:03 | Q1,00 | PCWP | | | 7 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 | | | | ----------------------------------------------------------------------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2)
- automatic DOP: Computed Degree of Parallelism is 2 统计信息
----------------------------------------------------------
1000941 recursive calls
4 db block gets
1000516 consistent gets
1842 physical reads
0 redo size
6026847 bytes sent via SQL*Net to client
1006 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
9 sorts (memory)
0 sorts (disk)
1 rows processed
--上面的执行计划及v$pq_sesstat都显示系统启用了并行处理,并行度为2
13:57:44 SYS@orcl> select * from v$pq_sesstat; STATISTIC LAST_QUERY SESSION_TOTAL
------------------------------ ---------- -------------
Queries Parallelized 0 1
DML Parallelized 0 0
DDL Parallelized 0 0
DFO Trees 0 1
Server Threads 0 0
Allocation Height 0 0
Allocation Width 0 0
Local Msgs Sent 0 553
Distr Msgs Sent 0 0
Local Msgs Recv'd 0 553
Distr Msgs Recv'd 0 0 已选择11行。 已用时间: 00: 00: 00.01

为了使示例更加有说服力,我们再来试一下普通管道函数+HINT强制并行看看:

16:02:36 SYS@orcl> select /*+ parallel */SCOTT.pipe_test(CURSOR(SELECT a||','||b from big_data)) FROM DUAL;

已选择 1 行。

已用时间:  00: 00: 43.34

执行计划
----------------------------------------------------------
Plan hash value: 2452824241 ------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 (0)| 00:00:01 |
| 1 | VIEW | | 8168 | 414K| 16 (0)| 00:00:01 |
| 2 | COLLECTION ITERATOR PICKLER FETCH| PIPE_TEST | 8168 | | 16 (0)| 00:00:01 |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------------------------ Note
-----
- dynamic sampling used for this statement (level=2)
- automatic DOP: Computed Degree of Parallelism is 1 统计信息
----------------------------------------------------------
1003093 recursive calls
18 db block gets
1000973 consistent gets
1628 physical reads
0 redo size
6026843 bytes sent via SQL*Net to client
1006 bytes received via SQL*Net from client
8 SQL*Net roundtrips to/from client
100 sorts (memory)
0 sorts (disk)
1 rows processed

由于普通函数不支持并行,所以即使+HINT强制并行,系统还是没有使用并行处理.耗时依然为40多秒.

如果不使用函数,使用普通的SQL,又是可以使用HINT强制并行的,如下:

15:59:07 SYS@orcl> select /*+ parallel */ a||','||b from big_data;

已选择999999行。

已用时间:  00: 00: 04.09

执行计划
----------------------------------------------------------
Plan hash value: 2638980575 --------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 968K| 7565K| 234 (3)| 00:00:03 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM)| :TQ10000 | 968K| 7565K| 234 (3)| 00:00:03 | Q1,00 | P->S | QC (RAND) |
| 3 | PX BLOCK ITERATOR | | 968K| 7565K| 234 (3)| 00:00:03 | Q1,00 | PCWC | |
| 4 | TABLE ACCESS FULL| BIG_DATA | 968K| 7565K| 234 (3)| 00:00:03 | Q1,00 | PCWP | |
-------------------------------------------------------------------------------------------------------------- Note
-----
- dynamic sampling used for this statement (level=2)
- automatic DOP: Computed Degree of Parallelism is 2 统计信息
----------------------------------------------------------
6 recursive calls
0 db block gets
1577 consistent gets
1520 physical reads
0 redo size
13467035 bytes sent via SQL*Net to client
733742 bytes received via SQL*Net from client
66668 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
999999 rows processed

通过上面的示例可以看到,并行处理可以大大加速数据的处理,几乎成倍的提升性能.

但并不是并行度为几,就会提示几倍的性能,它受硬件环境,优化器内部算法,PL/SQL引擎解析等等的约束.

总之,并行处理给我们带来的性能提升是很大的,所以在某些场景使用并行编程也是很必要的.

初试PL/SQL并行编程的更多相关文章

  1. PL/SQL存储过程编程

    PL/SQL存储过程编程 /**author huangchaobiao *Email:huangchaobiao111@163.com */ PL/SQL存储过程编程(上) 1. Oracle应用编 ...

  2. oracle PL/SQL基础编程

    PL/SQL(Procedural Language/SQL)是oracle中引入的一种过程化编程语言 PLS-00103:出现符号"declare"在需要下列之一时 符号&quo ...

  3. PL/SQL 基础编程

    PL/Sql 编程 PL/Sql结构 [declare] --声明变量 begin --执行部分 [exception] ---异常处理部分 end PL/Sql  基本数据类型 数值类型 1. nu ...

  4. Oracle数据库—— PL/SQL进阶编程

    一.涉及内容 1.掌握PL/SQL程序块的结构 2.理解并熟练掌握各种变量的应用. 二.具体操作 1.创建一个表messages,该表只有一个字段results 类型是number(2),编写一个块, ...

  5. Oracle数据库—— PL/SQL基础编程

    一.涉及内容 1. 掌握PL/SQL程序块的结构,理解并熟悉各种变量的应用. 二.具体操作 (一)使用system用户登录SQL*PLUS,使用SQL语句创建用户:u_你的姓名首字母(例如:u_zs) ...

  6. Oracle PL/SQL 高级编程

    1. 复合数据类型--记录类型 Ø        语法格式 type  类型名 is   record ( 字段1  字段1类型 [not null]:=表达式1; 字段2  字段2类型 [not n ...

  7. 【学亮IT手记】PL/SQL游标编程

    游标提供了一种从表中检索数据并进行操作的灵活手段,主要用在服务器上,处理由客户端发送给服务器端的sql语句,或者是批处理.存储过程.触发器中的数据处理请求. 显式游标 是由用户声明和操作的一种游标,通 ...

  8. Oracle PL/SQL DBA 编程实践基础

    [附:一文一图]

  9. ORACLE PL/SQL编程详解

    ORACLE PL/SQL编程详解 编程详解 SQL语言只是访问.操作数据库的语言,并不是一种具有流程控制的程序设计语言,而只有程序设计语言才能用于应用软件的开发.PL /SQL是一种高级数据库程序设 ...

随机推荐

  1. VS2013无法链接到TFS (转)

    VS2013无法链接到TFS(Visual studio online),错误TF31001,TF31002   TF31002: Unable to connect to VisualStudio ...

  2. WinSock网络编程基础(3)server

    上一篇讲的是简单的发送数据的客户端的实现.接下来讲的是如何实现收发数据服务器.这里说的服务器其实就是一个进程,它需要等待任意数量的客户端与之建立起连接,以便响应它们的请求. 服务器必须在已知的名称上监 ...

  3. ROS使用rqt_console

    打开一个新的终端在里面输入: sudo apt-get install ros-hydro-rqt ros-hydro-rqt-common-plugins ros-hydro-turtlesim 安 ...

  4. C++学习之运算符重载的总结

    C++学习之运算符重载的总结              运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用域不同类型的数据导致不同行为的发生,C++为运算符重载提供了一种方法,即运算符重载函数 ...

  5. Java中的变量与变量的作用域

    关于Java中的变量及变量的作用域 关于Java中的变量及变量的作用域 0. 变量的概念 在程序运行期间,系统可以为程序分配一块内存单元,用来存储各种类型的数据.系统分配的内存单元要使用一个标记符来标 ...

  6. iScroll 4,把禁掉的:active样式还给我~

    iScroll这个移动端的滚动神器大家都非常熟悉了,直到现在仍是实现移动端Web滚动的首选方案之一... 当我接触移动端Web时iScroll已经有两个版本了,iScroll 4和iScroll 5, ...

  7. 一周学会Mootools 1.4中文教程:(1)Dom选择器

    利器: 君欲善其事须先利其器,好吧因为我们的时间比较紧迫,只有六天而已,那么六天的时间用死记硬背的方式学会Mt犹如天方夜谭,因此我们需要借鉴一下Editplus的素材栏帮我们记忆就好了,当我们需要用到 ...

  8. windows下安装testlink

    因为项目中一直没有使用任何测试用例管理工具,如果需要的时候都是个人写在的excle里各自保存,因为没有系统的记录当时测试方法和测试用例,每次需要再次测试已有的功能时,因为时间太长,而往往记不得当时是怎 ...

  9. python读取word表格内容(1)

    1.首页介绍下word表格内容,实例如下: 每两个表格后面是一个合并的单元格

  10. while和for可以相互转换例子

    //while和for循环可以相互转换,以下为简单格式: ;;) A; 等价于 : ) { A; ; } /* Name:while和for可以相互转换例子 Copyright: By.不懂网络 Au ...