天天看点

Oracle Parallel

背景:在系统中,有2个4核心的CPU,那么一共8个逻辑CPU。每当ORACLE进行查询时,就会产生一个session,对于oracle 每个session占用一个CPU。当整个系统只有一个人在用的时候,剩下7个CPU,是空闲状态。那么就可以用parallel语句合理利用起来剩下7个CPU。

注意:当系统有很多用户连接时,开启parallel不是一个明确的选择。

1.  用途

强行启用并行度来执行当前SQL。这个在Oracle 9i之后的版本可以使用,之前的版本现在没有环境进行测试。也就是说,加上这个说明,可以强行启用Oracle的多线程处理功能。举例的话,就像电脑装了多核的CPU,但大多情况下都不会完全多核同时启用(2核以上的比较明显),使用parallel说明,就会多核同时工作,来提高效率。

但本身启动这个功能,也是要消耗资源与性能的。所有,一般都会在返回记录数大于100万时使用,效果也会比较明显。

2.

启用Parallel前的忠告:只有在需要处理一个很大的任务,如需要几十分钟,几个小时的作业中,并且要有足够的系统资源的情况下(这些资源包括cpu,内存,io),您才应该考虑使用parallel。否则,在一个多并发用户下,系统本身资源负担已经很大的情况下,启用parallel,将会导致某一个会话试图占用了所有的资源,其他会话不得不去等待,从而导致系统系能反而下降的情况,一般情况下,oltp系统不要使用parallel,oltp系统中可以考虑去使用。

Parallel分类

a)并行查询parallel query

b)并行dml parallel dml pdml

c)并行ddl parallel ddl pddl

A)并行查询:

开启并行查询就是对于某个TABLE

<p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span class="pln">  </span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span class="pln">SQL</span><span class="pun">></span><span class="pln">alter table TABLE_NAME </span><span style="background-color: rgb(255, 153, 204);"><span class="pln">parallel</span></span><span class="pln"> </span><span class="lit">8</span></p><span class="pln">  </span><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"><span class="pun">将对于</span><span class="pln">TABLE_NAME </span><span class="pun">这个表的查询</span><span class="pln"> </span><span class="pun">改为</span><span class="lit">8</span><span class="pun">核</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"></p>      
<p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"></p><pre style="white-space: pre-wrap; word-wrap: break-word;"><span class="pln">SQL</span><span class="pun">></span><span class="kwd">select</span><span class="pln"> </span><span class="com">/*+ parallel(t1 8) */</span><span class="pln"> count</span><span class="pun">(*)</span><span class="pln"> </span><span class="kwd">from</span><span class="pln"> t1</span><span class="pun">;</span>      
只对于本次SQL有效      
//测试不好用,没有加快      
<p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"></p><pre style="white-space: pre-wrap; word-wrap: break-word;"><span class="pln">SQL</span><span class="pun">></span><span class="pln">alter table t1 noparallel</span>      
取消并行设置      
B)并行dml      
并行dml包括insert,update,delete,merge,在pdml期间,oracle可以使用多个并行执行服务器来执行insert,update,delete,merge,多个会话同时执行,同时每个会话(并发进程)都有自己的undo段,都是独立的一个事务,这些事务要么由pdml协调器进程提交,要么都rollback。

在一个有充足I/o带宽的多cpu主机中,对于大规模的dml,速度可能会有很大的提升,尤其是在大型的数据仓库环境中。

并行需要:

 
       
<p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; text-indent: 2em;"><span class="pln"> </span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; text-indent: 2em;"><span class="pln">SQL</span><span class="pun">></span><span class="pln"> alter session enable parallel dml</span><span class="pun">;</span><span class="pln"> </span><span class="pun">开启</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; text-indent: 2em;"><span class="pln">SQL</span><span class="pun">></span><span class="pln"> alter session disable parallel dml</span><span class="pun">;</span><span class="pln"> </span><span class="pun">关闭</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px; text-indent: 2em;"><span class="com">//测试不好用</span></p><p style="margin-top: 0px; margin-bottom: 0px; padding-top: 0px; padding-bottom: 0px;"></p>      

详细讲解(没看太懂):

一、并行(Parallel)和OLAP系统

并行的实现机制是:首先,Oracle会创建一个进程用于协调并行服务进程之间的信息传递,这个协调进程将需要操作的数据集(比如表的数据块)分割成很多部分,称为并行处理单元,然后并行协调进程给每个并行进程分配一个数据单元。比如有四个并行服务进程,他们就会同时处理各自分配的单元,当一个并行服务进程处理完毕后,协调进程就会给它们分配另外的单元,如此反复,直到表上的数据都处理完毕,最后协调进程负责将每个小的集合合并为一个大集合作为最终的执行结果,返回给用户。

并行处理的机制实际上就是把一个要扫描的数据集分成很多小数据集,Oracle 会启动几个并行服务进程同时处理这些小数据集,最后将这些结果汇总,作为最终的处理结果返回给用户。

这种数据并行处理方式在OLAP系统中非常有用,OLAP系统的表通常来说都是非常大,如果系统的CPU比较多,让所有的CPU共同来处理这些数据,效果就会比串行执行要高得多。

然而对于OLTP系统,通常来讲,并行并不合适,原因是OLTP系统上几乎在所有的SQL操作中,数据访问路径基本上以索引访问为主,并且返回结果集非常小,这样的SQL操作的处理速度一般非常快,不需要启用并行。

二、并行处理的机制

当Oracle数据库启动的时候,实例会根据初始化参数:

 PARALLEL_MIN_SERVERS=n

的值来预先分配n个并行服务进程,当一条SQL被CBO判断为需要并行执行时发出SQL的会话进程变成并行协助进程,它按照并行执行度的值来分配进程服务器进程。

首先协调进程会使用ORACLE启动时根据参数: parallel_min_servers=n的值启动相应的并行服务进程,如果启动的并行服务器进程数不足以满足并行度要求的并行服务进程数,则并行协调进程将额外启动并行服务进程以提供更多的并行服务进程来满足执行的需求。然后并行协调进程将要处理的对象划分成小数据片,分给并行服务进程处理;并行服务进程处理完毕后将结果发送给并行协调进程,然后由并行协调进程将处理结果汇总并发送给用户。

刚才讲述的是一个并行处理的基本流程。实际上,在一个并行执行的过程中,还存在着并行服务进程之间的通信问题。

在一个并行服务进程需要做两件事情的时候,它会再启用一个进程来配合当前的进程完成一个工作,比如这样的一条SQL语句:

Select * from employees order by last_name;

假设employees表中last_name 列上没有索引,并且并行度为4,此时并行协调进程会分配4个并行服务进程对表employees进行全表扫描操作,因为需要对结果集进行排序,所以并行协调进程会额外启用4个并行服务进程,用于处理4个进程传送过来的数据,这新启用的用户处理传递过来数据的进程称为父进程,用户传出数据(最初的4个并行服务进程)成为子进程,这样整个并行处理过程就启用了8个并行服务进程。 其中每个单独的并行服务进程的行为叫作并行的内部操作,而并行服务进程之间的数据交流叫做并行的交互操作。

这也是有时我们发现并行服务进程数量是并行度的2倍,就是因为启动了并行服务父进程操作的缘故。

五、并行执行的使用范围

Oracle的并行技术在下面的场景中可以使用:

(1)Parallel Query(并行查询)

(2)Parallel DDL(并行DDL操作,如建表,建索引等)

(3)Parallel DML(并行DML操作,如insert,update,delete等)

5.1 并行查询

并行查询可以在查询语句,子查询语句中使用,但是不可以使用在一个远程引用的对象上(如DBLINK)。

一个查询能够并行执行,需要满足一下条件:

(1)SQL语句中有Hint提示,比如Parallel 或者 Parallel_index.

(2)SQL语句中引用的对象被设置了并行属性。

(3)多表关联中,至少有一个表执行全表扫描(Full table scan)或者跨分区的Index range SCAN。

如:select

SELECT      u_dump.VALUE

         || '/'

         || db_name.VALUE

         || '_ora_'

         || v$process.spid

         || NVL2 (v$process.traceid, '_' || v$process.traceid, NULL)

         || '.trc'

            "Trace File"

  FROM            v$parameter u_dump

               CROSS JOIN

                  v$parameter db_name

            CROSS JOIN

               v$process

         JOIN

            v$session

         ON v$process.addr = v$session.paddr

 WHERE       u_dump.name = 'user_dump_dest'

         AND db_name.name = 'db_name'

         AND v$session.audsid = SYS_CONTEXT ('userenv', 'sessionid');

Trace File

------------------------------------------------------------------------------

d:\app\administrator\diag\rdbms\orcl\orcl\trace/orcl_ora_5836.trc

d:\app\administrator\diag\rdbms\orcl\orcl\trace/orcl_ora_3048.trc

SQL> alter session set events '10046 trace name context forever,level 12';

会话已更改。

SQL> create table test parallel 4 as select * from dba_objects;

表已创建。

SQL> alter session set events '10046 trace name context off' ;

会话已更改。

这里用到了ORACLE的event 时间。 10046事件是用来跟踪SQL语句的。开启事件后,相关的信息会写道trace 文件中,这也是之前我们查看trace 文件名的原因。

有了trace文件, 我们可以用tkprof 工具,来查看trace 文件的内容。

关于tkprof 工具介绍,参考blog:

  使用 Tkprof 分析 ORACLE 跟踪文件

 http://blog.csdn.net/tianlesoftware/archive/2010/05/29/5632003.aspx

进入trace 目录,用tkprof命令生成txt 文件,然后查看txt 文件。

d:\app\Administrator\diag\rdbms\orcl\orcl\trace>tkprof orcl_ora_3048.trc test.txt sys=no

TKPROF: Release 11.2.0.1.0 - Development on 星期二 8月 31 23:45:25 2010

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

d:\app\Administrator\diag\rdbms\orcl\orcl\trace>

5.2.2 创建索引的并行执行

创建索引时使用并行方式在系统资源充足的时候会使性能得到很大的提高,特别是在OLAP系统上对一些很大的表创建索引时更是如此。 以下的创建和更改索引的操作都可以使用并行:

Create index

Alter index … rebuild

Alter index … rebuild partition

Alter index … split partition

一个简单的语法:create index t_ind on t(id) parallel 4;

监控这个过程和5.2.1 中表一样,需要通过10046事件。 这里就不多说了。

有关减少创建时间方法,参考blog:

   如何加快建 index 索引 的时间

  http://blog.csdn.net/tianlesoftware/archive/2010/07/11/5664019.aspx

总结:

使用并行方式,不论是创建表,修改表,创建索引,重建索引,他们的机制都是一样的,那就是Oracle 给每个并行服务进程分配一块空间,每个进程在自己的空间里处理数据,最后将处理完毕的数据汇总,完成SQL的操作。

5.3 并行DML 操作

Oracle 可以对DML操作使用并行执行,但是有很多限制。 如果我们要让DML 操作使用并行执行,必须显示地在会话里执行如下命令:

SQL> alter session enable parallel dml;

会话已更改。

只有执行了这个操作,Oracle 才会对之后符合并行条件的DML操作并行执行,如果没有这个设定,即使SQL中指定了并行执行,Oracle也会忽略它。

5.3.1 delete,update和merge 操作

Oracle 对Delete,update,merge的操作限制在,只有操作的对象是分区表示,Oracle 才会启动并行操作。原因在于,对于分区表,Oracle 会对每个分区启用一个并行服务进程同时进行数据处理,这对于非分区表来说是没有意义的。

5.3.2 Insert 的并行操作

实际上只有对于insert into … select … 这样的SQL语句启用并行才有意义。 对于insert into .. values… 并行没有意义,因为这条语句本身就是一个单条记录的操作。

Insert 并行常用的语法是:

 Insert into t select * from t1;

 这条SQL 语句中,可以让两个操作insert 和select 分别使用并行,这两个并行是相互独立,互补干涉的,也可以单独使用其中的一个并行。