Oracle parallel理解

并行概念

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

这种数据并行处理方式在OLAP系统中非常有用,OLAP系统的表通常来说都非常大,如果系统的CPU比较多,那么可以让所有的CPU共同来处理这些数据,效果就会比串行执行要好得多。对于OLTP系统,通常而言,并行并不合适,原因是OLTP系统上几乎在所有的SQL操作中,数据访问路径基本上以索引访问为主,并且返回结果集非常小,这样的SQL操作的处理速度一般非常快,不需要启用并行。

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

相关参数

和并行相关的参数较多,下面给出几个常见的参数,其它参数请参考官方文档:

CPU_COUNT

参数类型 Integer
默认值为 0
可修改 ALTER SYSTEM
值范围为 0至无限

CPU_COUNT指定了可供Oracle数据库使用的CPU的数量。在核心架构上,它指定了可用的CPU核心的数量。Oracle数据库的各种组件是根据CPU的数量来配置的,例如优化器、并行查询和资源管理器。

如果CPU_COUNT被设置为0(其默认设置),那么Oracle数据库会持续监控操作系统报告的CPU数量,并使用当前的计数。如果CPU_COUNT被设置为0以外的值,那么Oracle数据库将使用这个计数而不是CPU的实际数量,从而禁用动态CPU重新配置。当启用资源管理器时,设置CPU_COUNT将CPU的利用率限制在大约CPU_COUNT处理器。

PARALLEL_THREADS_PER_CPU

参数类型 Integer
默认值 Operating system-dependent, usually 2
可修改性 ALTER SYSTEM
值范围 Any nonzero number

注意:这个参数适用于单实例和RAC环境的并行执行。
PARALLEL_THREADS_PER_CPU确定实例的默认并行度和并行自适应及负载均衡算法。参数描述并行执行期间每个CPU能处理的并行执行进程或线程数。
默认值和平台有关,且在大多数情况下是足够的。当一个具有代表性的并行查询执行,且机器出现过载现象时,那么,你应该减少该参数的值。如果系统是IO限制的,你应该增加该参数。

PARALLEL_MIN_SERVERS

参数类型 Integer
默认值 0
可修改性 ALTER SYSTEM
值范围 0 to value of PARALLEL_MAX_SERVERS
Oracle RAC 多个实例可以有不同的值

注意:该参数使用单实例和RAC环境的并行执行。
PARALLEL_MIN_SERVERS确定实例上并行执行进程的最小数。该值是实例启动时Oracle创建的并行执行进程的数目。

默认值为0,确定实例上并行执行进程的最小数,该值是Oracle实例启动时创建的并行执行进程的数目,可以使用“ ps -ef|grep ora_p0”来查看。Oracle RAC多个实例可以有不同的值。若修改了该值,则只有当数据库实例重启的情况下后台进程数才会变化。

PARALLEL_MAX_SERVERS

默认值为PARALLEL_THREADS_PER_CPU * CPU_COUNT * concurrent_parallel_users * 5。该参数确定一个实例并行执行进程和并行恢复进程的最大数。当需求增加时,Oracle数据库从实例启动时的进程数增加到该参数值。在默认值计算公式中,实例上赋予正在使用的concurrent_parallel_users的值和内存管理设置相关。如果自动内存管理被关闭(手工模式),那么concurrent_parallel_users为1。如果PGA自动内存管理被开启,那么concurrent_parallel_users的值为2.如果除了PGA自动内存管理,全局内存管理或SGA内存目标也被使用,那么,concurrent_parallel_users为4。Oracle RAC多个实例可以有不同值。

如下参考Doc ID 1968840.1

从11gR2开始,有一种新的方法来计算PARALLEL_MAX_SERVERS的默认值。 在11gR2中,PARALLEL_MAX_SERVERS的值以PROCESSES-15为上限。

在12c中,PARALLEL_MAX_SERVERS的值由PROCESSES - N来限定,其中N是一个内部计算的结果,该计算估计了需要为特定数据库保留的最大背景进程的数量。

例如,使用15的值,如11gR2中:

parallel_threads_per_cpu = 2
cpu_count = 4
pga_aggregate_target = 500M
sga_target = 900M
processes = 150

parallel_max_servers = 2 * 4 * 4 * 5 = 160
default value of: parallel_max_servers = min( 150-15 , 160 ) = 135

因此,通过这些值,我们可以得到parallel_max_servers的默认值为135。

注意,如果parallel_max_servers由于进程值的原因而减少,那么你会在警报日志中看到类似以下的情况(例如在实例启动时)。

Mon May 06 18:43:06 2013
Adjusting the default value of parameter parallel_max_servers
from 160 to 135 due to the value of parameter processes (150)
Starting ORACLE instance (normal)

PARALLEL_DEGREE_POLICY

参数类型 String
语法 PARALLEL_DEGREE_POLICY = { MANUAL | LIMITED | AUTO }
默认值 MANUAL
可修改性 ALTER SESSION, ALTER SYSTEM
是否基础 No

注意:该参数尽量不要修改为AUTO,因为相关的Bug较多,一般使用MANUAL即可。

PARALLEL_DEGREE_POLICY确定是否开启自动并行度,语句排队和内存并行执行。
值:
注意:如果一个PARALLEL hint在语句级被使用,无论PARALLEL_DEGREE_POLICY值设置成什么,自动并行度都将被开启。
■ MANUAL
关闭自动并行度,语句排队和内存并行执行。这恢复并行执行到11.2之前的行为。这是默认设置。
■ LIMITED
对某些语句开启自动并行执行,但语句排队和内存并行执行被关闭。自动并行度仅仅适用那些存取显式用PARALELL语句标示默认并行度的表或索引的语句。并不存取这些被显式标示默认并行度的表或索引的语句将保持手工(MANUAL)行为。
■ AUTO
开启自动并行度,语句排队和内存并行执行。

PARALLEL_DEGREE_LIMIT

参数类型 String
语法 PARALLEL_DEGREE_LIMIT = { CPU | IO | integer }
默认值 CPU
可更改性 ALTER SESSION, ALTER SYSTEM
是否基础 No

在并行度自动调整的情况下,Oracle自动决定一个语句是否并行执行和用什么并行度执行。优化器基于语句的资源需求自动决定一个语句的并行度。
然而,为了确保并行服务器进程不会导致系统过载,优化器会限制使用的并行度。这个限制通过PARALLEL_DEGREE_LIMIT来强制实施。
值:
■ CPU
最大并行度被系统CPU数限制。计算限制的公式为PARALLEL_THREADS_PER_CPU *CPU_COUNT * 可用实例数(默认为簇中打开的所有实例,但也能通过PARALLEL_INSTANCE_GROUP或service定义来约束),这是默认的。
■ IO
优化器能用的最大并行度被系统的IO容量限制。系统总吞吐除以每个进程的最大IO带宽计算出。为了使用该IO设置,你必须在系统上运行DBMS_RESOURCE_MANAGER.CALIBRATE_IO过程。该过程将计算系统总吞吐和单个进程的最大IO带宽。
■ integer
当自动并行度被激活时,该参数的数字值确定优化器为一个SQL语句能选择的最大并行度。PARALLEL_DEGREE_POLICY被设置为AUTO或LIMITED时,自动并行度才可以使用。

PARALLEL_FORCE_LOCAL

参数类型 Boolean
默认值 false
可修改性 ALTER SESSION, ALTER SYSTEM
值范围 true | false
是否基础 No
PARALLEL_FORCE_LOCAL控制Oracle RAC环境下的并行执行。默认情况,被选择执行一个SQL语句的并行服务器进程能在簇中任何或所有Oracle RAC节点上操作。通过设置PARALLEL_FORCE_LOCAL为true,并行服务器进程被限制从而都在查询协调器驻留的同一个Oracle RAC节点上操作(语句被执行的节点上) 。

PARALLEL_MIN_PERCENT

参数类型 Integer
默认值 0
可修改性 ALTER SESSION
值范围 0 to 100
Oracle RAC 多个实例能有不同的值

PARALLEL_MIN_PERCENT使得你确定并行执行需要并行执行进程数的最小百分比。设置该参数确保除非有足够的资源可用,否则,不会执行并行操作。默认值0意味着没进程的最小百分比被设置。
考虑以下设置:
PARALLEL_MIN_PERCENT = 50
PARALLEL_MIN_SERVERS = 5
PARALLEL_MAX_SERVERS = 10
如果十个并行执行进程中的8个处于繁忙状态,仅两个进程可用。如果接着你提交一个并行度8的查询,那么,最小50%不能被满足。
你能和PARALLEL_ADAPTIVE_MULTI_USER参数一起使用该参数。在多用户环境,一个单独的用户或应用能设置PARALLEL_MIN_PERCENT为一个有足够的系统资源和可接受的并行度被返回时使用的最小值。

PARALLEL_ADAPTIVE_MULTI_USER

参数类型 Boolean
默认值 true
可修改性 ALTER SYSTEM
取值范围 true | false

被设置为true时,使自适应算法可用,该算法被设计来改善使用并行的多用户环境的性能。
该算法在查询开始时基于负载来自动减少被要求的并行度。实际的并行度基于默认、来自表或hints的并行度,然后除以一个缩减因数。该算法假设系统已经在单用户环境下进行了最优调整。表和hints用默认的并行度。

PARALLEL_MIN_TIME_THRESHOLD

确定一个语句被考虑采用自动并行度前一个语句将用的最小执行时间。默认值为AUTO,表示10s。只有PARALLEL_DEGREE_POLICY被设置为AUTO或LIMITED时,自动并行度才被开启。

MANUAL:关闭自动并行度,语句排队和内存并行执行。这恢复并行执行到11.2之前的行为。这是默认设置。

LIMITED:对某些语句开启自动并行执行,但语句排队和内存并行执行被关闭。自动并行度仅仅适用那些存取显式用PARALELL语句标示默认并行度的表或索引的语句。并不存取这些被显式标示默认并行度的表或索引的语句将保持手工(MANUAL)行为。

AUTO:开启自动并行度,语句排队和内存并行执行。

PARALLEL_SERVERS_TARGET

参数类型 Integer
默认值 PARALLEL_THREADS_PER_CPU * CPU_COUNT * concurrent_parallel_users * 2
可修改性 ALTER SYSTEM
值范围 0 to PARALLEL_MAX_SERVERS
是否基础 No

PARALLEL_SERVERS_TARGET确定语句排队被采用前运行一个语句允许的并行服务器进程数。当参数PARALLEL_DEGREE_POLICY被设置为AUTO,且必需的并行服务器进程不可用时,Oracle将排队要求并行执行的SQL语句。一旦系统上活的并行服务器进程数等于PARALLEL_SERVERS_TARGETS,语句排队将开始。默认地,PARALLEL_SERVERS_TARGETS被设置低于系统上允许的并行服务进程最大数(PARALLEL_MAX_SERVERS),以确保每个并行语句将获得需要的并行服务资源,同时,也避免因为过多的并行服务器进程数而导致系统过载。
一个实例上运行的默认并行度的并发并行用户和内存管理设置相关。如果自动内存管理被关闭(手工模式),那么,并发并行用户数为1.如果PGA自动内存管理被开启,并发并行用户为2。如果除了PGA内存自动管理,还有全局内存管理和SGA内存目标被使用,那么,并发并行用户数为4。
注意即使语句排队被激活,所有串行语句(非并行的)将立即执行。

废弃参数

parallel_automatic_tuning

parallel_server_instances

parallel_io_cap_enabled

parallel_server

并行执行的使用范围

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

(1)PARALLEL QUERY(并行查询,简称PQ)。

(2)PARALLEL DDL(并行DDL操作,简称PDDL,例如建表、建索引等)。

(3)PARALLEL DML(并行DML操作,简称PDML,例如INSERT、UPDATE、DELETE等)。

并行查询(PQ)

并行查询可以在查询语句、子查询语句中使用,但是不可以使用在一个远程引用的对象上(例如DBLINK)。当一条SQL语句发生全表扫描、全分区扫描及索引快速全扫描的时候,若优化器满足下面的条件之一就可以使用并行处理:

① 会话级别,会话设置了强制并行,例如,“ALTER SESSION FORCE PARALLEL QUERY PARALLEL 4;”,执行“SELECT COUNT(*) FROM TB_PART_LHR;”,这里的TB_PART_LHR为分区表。

② 语句级别,SQL语句中有Hint提示,例如,使用PARALLEL或者PARALLEL_INDEX。如,“SELECT /*+ PARALLEL(T 4) */ FROM T;”。

③ SQL语句中引用的对象被设置了并行属性。在表和索引的定义中增加并行度属性,该属性可以在创建表和索引时设置,也可对已创建的表和索引的并行度属性进行修改。例如,“ALTER TABLE TB_NAME PARALLEL 4;”、“ALTER TABLE TB_NAME PARALLEL (DEGREE DEFAULT);”。取消表或索引的并行度的SQL为:“ALTER TABLE TB_NAME NOPARALLEL;”。

示例如下:

SYS@orclasm > ALTER TABLE SH.SALES PARALLEL (DEGREE 10);
Table altered.
SYS@orclasm >  SELECT DEGREE FROM DBA_TABLES WHERE TABLE_NAME='SALES' AND OWNER='SH';
DEGREE
--------------------
        10
SYS@orclasm > ALTER TABLE SH.SALES PARALLEL (DEGREE DEFAULT);
Table altered.
SYS@orclasm > SELECT DEGREE FROM DBA_TABLES WHERE TABLE_NAME='SALES' AND OWNER='SH';
DEGREE
-------------------
  DEFAULT
SYS@orclasm >  ALTER TABLE  SH.SALES NOPARALLEL;
Table altered.
SYS@orclasm > SELECT DEGREE FROM DBA_TABLES WHERE TABLE_NAME='SALES' AND OWNER='SH';
DEGREE
-------------------
         1
SYS@orclasm > CREATE TABLE SCOTT.AA AS SELECT * FROM DUAL;
Table created.
SYS@orclasm >  SELECT DEGREE FROM DBA_TABLES WHERE TABLE_NAME='AA' AND OWNER='SCOTT';
DEGREE
--------------------
         1

在日常使用上,一般不建议在对象级别定义并行度,因为这会导致相关对象的操作都变为并行处理,而并行处理会占用大量的CPU资源,导致数据库整体性能失控。一般在会话或语句级别进行处理。

并行DDL操作(PDDL)

表或索引的CREATE或ALTER操作可以使用并行。例如,以下表操作可以使用并行执行:

建表:CREATE TABLE … AS SELECT(CTAS)
表移动:ALTER TABLE … MOVE
表分区移动:ALTER TABLE … MOVE PARTITION
表分区并行分解:ALTER TABLE … SPLIT PARTITION
表分区并行合并:ALTER TABLE … COALESCE PARTITION
创建和校验约束:ALTER TABLE … ADD CONSTRAINT
创建索引:CREATE INDEX
重建索引:ALTER INDEX … REBULD
重建索引分区:ALTER INDEX … REBULD PARTITION
索引分区的分解:ALTER INDEX … SPLIT PARTITION

并行DML操作(PDML)

Oracle可以对DML操作使用并行执行。如果要让DML操作使用并行执行,那么必须显式地在会话里执行如下命令

ALTER SESSION ENABLE PARALLEL DML;

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

以下给出一个并行UPDATE的示例:

LHR@TEST> CREATE TABLE TB_LHR20160518 AS  SELECT * FROM DBA_OBJECTS;
Table created.
LHR@TEST> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL,NULL,'BASIC +PARALLEL'));
PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------
Plan hash value: 2194116729
-----------------------------------------------------------------------------
| Id  | Operation             | Name           |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------
|   0 | UPDATE STATEMENT      |                |        |      |            |
|   1 |  UPDATE               | TB_LHR20160518 |        |      |            |
|   2 |   PX COORDINATOR      |                |        |      |            |
|   3 |    PX SEND QC (RANDOM)| :TQ10000       |  Q1,00 | P->S | QC (RAND)  |
|   4 |     PX BLOCK ITERATOR |                |  Q1,00 | PCWC |            |
|   5 |      TABLE ACCESS FULL| TB_LHR20160518 |  Q1,00 | PCWP |            |
-----------------------------------------------------------------------------
12 rows selected.
LHR@TEST> EXPLAIN PLAN FOR UPDATE /*+ PARALLEL (T1,4) */ TB_LHR20160518 T1 SET OBJECT_NAME='LHR';
Explained.
LHR@TEST> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL,NULL,'BASIC +PARALLEL'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2194116729
-----------------------------------------------------------------------------
| Id  | Operation             | Name           |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------
|   0 | UPDATE STATEMENT      |                |        |      |            |
|   1 |  UPDATE               | TB_LHR20160518 |        |      |            |
|   2 |   PX COORDINATOR      |                |        |      |            |
|   3 |    PX SEND QC (RANDOM)| :TQ10000       |  Q1,00 | P->S | QC (RAND)  |
|   4 |     PX BLOCK ITERATOR |                |  Q1,00 | PCWC |            |
|   5 |      TABLE ACCESS FULL| TB_LHR20160518 |  Q1,00 | PCWP |            |
-----------------------------------------------------------------------------
12 rows selected.
LHR@test> ALTER SESSION ENABLE  PARALLEL DML;
Session altered.
LHR@TEST> EXPLAIN PLAN FOR UPDATE /*+ PARALLEL (T1,4) */ TB_LHR20160518 T1 SET OBJECT_NAME='LHR';
Explained.
LHR@TEST> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL,NULL,'BASIC +PARALLEL'));
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------
Plan hash value: 3729706116
-----------------------------------------------------------------------------
| Id  | Operation             | Name           |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------
|   0 | UPDATE STATEMENT      |                |        |      |            |
|   1 |  PX COORDINATOR       |                |        |      |            |
|   2 |   PX SEND QC (RANDOM) | :TQ10000       |  Q1,00 | P->S | QC (RAND)  |
|   3 |    UPDATE             | TB_LHR20160518 |  Q1,00 | PCWP |            |
|   4 |     PX BLOCK ITERATOR |                |  Q1,00 | PCWC |            |
|   5 |      TABLE ACCESS FULL| TB_LHR20160518 |  Q1,00 | PCWP |            |
-----------------------------------------------------------------------------
12 rows selected.

通过执行计划可以看出,只有执行了“ALTER SESSION ENABLE PARALLEL DML;”后,UPDATE操作才真正地实现了并行操作,如果不执行该语句,那么只是执行了并发查询,并没有实现并发更新操作。

下表列出了这3种并行处理方式的开启及禁用语句:

类别 区别
并行查询(PQ) 默认 开启
查询 SELECT D.PQ_STATUS FROM V$SESSION D WHERE D.SID=USERENV('sid');
启用、禁用 ALTER SESSION ENABLE PARALLEL QUERY;--启用
ALTER SESSION FORCE PARALLEL QUERY PARALLEL n; --强制开启
ALTER SESSION DISABLE PARALLEL QUERY; --禁用
并行DDL(PDDL) 默认 开启
查询 SELECT D.PDDL_STATUS FROM V$SESSION D WHERE D.SID=USERENV('sid');
启用、禁用 ALTER SESSION ENABLE PARALLEL DDL; --启用
ALTER SESSION FORCE PARALLEL DDL PARALLEL n; --强制开启
ALTER SESSION DISABLE PARALLEL DDL; --禁用
并行DML(PDML) 默认 关闭
查询 SELECT D.PDML_STATUS FROM V$SESSION D WHERE D.SID=USERENV('sid');
启用、禁用 ALTER SESSION ENABLE PARALLEL DML; --启用
ALTER SESSION FORCE PARALLEL DML PARALLEL n; --强制开启
ALTER SESSION DISABLE PARALLEL DML; --禁用

RAC中的并行

如果连接Oracle RAC数据库,那么一个节点上的并发操作可以分布到多个节点上同时执行。可以使用视图GV$PX_SESSION查询并行会话的进程

这是一个Oracle 11g的RAC环境,下面建立一张测试表,建立过程中设置表的并行度:

[ZFWWLHRDB1:oracle]:/oracle>ORACLE_SID=raclhr1
[ZFWWLHRDB1:oracle]:/oracle>sqlplus / as sysdba
SQL*Plus: Release 11.2.0.4.0 Production on Fri Sep 30 14:52:23 2016
Copyright (c) 1982, 2013, Oracle.  All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
SYS@raclhr1> show parameter cluster
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
cluster_database                     boolean     TRUE
cluster_database_instances           integer     2
cluster_interconnects                string
SYS@raclhr1> CREATE TABLE T_PARALLEL_LHR NOLOGGING PARALLEL 4
  2   AS SELECT A.* FROM DBA_OBJECTS A, DBA_TABLES
  3   WHERE ROWNUM <= 5000000;
Table created.
SYS@raclhr1> SELECT * FROM V$MYSTAT WHERE ROWNUM<=1;
       SID STATISTIC#      VALUE
---------- ---------- ----------
       167          0          0
SYS@raclhr1> set autot on
SYS@raclhr1> SET LINESIZE 9999
SYS@raclhr1> SET PAGESIZE 9999
SYS@raclhr1> SELECT COUNT(*) FROM T_PARALLEL_LHR a,T_PARALLEL_LHR b where rownum<=1000000;
  COUNT(*)
----------
   1000000
Execution Plan
----------------------------------------------------------
Plan hash value: 1691788013
-------------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name           | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                |     1 |  2057M  (5)|999:59:59 |        |      |            |
|   1 |  SORT AGGREGATE             |                |     1 |            |          |        |      |            |
|*  2 |   COUNT STOPKEY             |                |       |            |          |        |      |            |
|   3 |    PX COORDINATOR           |                |       |            |          |        |      |            |
|   4 |     PX SEND QC (RANDOM)     | :TQ10001       |    23T|  2057M  (5)|999:59:59 |  Q1,01 | P->S | QC (RAND)  |
|*  5 |      COUNT STOPKEY          |                |       |            |          |  Q1,01 | PCWC |            |
|   6 |       MERGE JOIN CARTESIAN  |                |    23T|  2057M  (5)|999:59:59 |  Q1,01 | PCWP |            |
|   7 |        PX BLOCK ITERATOR    |                |  4857K|  5396   (1)| 00:01:05 |  Q1,01 | PCWC |            |
|   8 |         TABLE ACCESS FULL   | T_PARALLEL_LHR |  4857K|  5396   (1)| 00:01:05 |  Q1,01 | PCWP |            |
|   9 |        BUFFER SORT          |                |  4857K|  2057M  (5)|999:59:59 |  Q1,01 | PCWP |            |
|  10 |         PX RECEIVE          |                |  4857K|  5396   (1)| 00:01:05 |  Q1,01 | PCWP |            |
|  11 |          PX SEND BROADCAST  | :TQ10000       |  4857K|  5396   (1)| 00:01:05 |  Q1,00 | P->P | BROADCAST  |
|  12 |           PX BLOCK ITERATOR |                |  4857K|  5396   (1)| 00:01:05 |  Q1,00 | PCWC |            |
|  13 |            TABLE ACCESS FULL| T_PARALLEL_LHR |  4857K|  5396   (1)| 00:01:05 |  Q1,00 | PCWP |            |
-------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(ROWNUM<=1000000)
   5 - filter(ROWNUM<=1000000)
Note
-----
   - dynamic sampling used for this statement (level=4)
Statistics
----------------------------------------------------------
        112  recursive calls
          8  db block gets
      72078  consistent gets
      74257  physical reads
          0  redo size
        526  bytes sent via SQL*Net to client
        520  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          4  sorts (disk)
          1  rows processed

从执行计划可以看到,Oracle选择了并行执行。

新建立一个会话,在执行上面这个并行查询的同时查询GV$PX_SESSION(或GV$PX_PROCESS)视图:

SYS@raclhr1> SELECT * FROM GV$PX_SESSION WHERE QCSID=167;
   INST_ID SADDR                   SID    SERIAL#      QCSID  QCSERIAL#  QCINST_ID SERVER_GROUP SERVER_SET    SERVER#     DEGREE REQ_DEGREE
---------- ---------------- ---------- ---------- ---------- ---------- ---------- ------------ ---------- ---------- ---------- ----------
         1 07000100538364A0        199         35        167          5          1            1          1          1          4          4
         1 0700010053894FC0        230         35        167          5          1            1          1          2          4          4
         1 0700010053607480         10         37        167          5          1            1          2          1          4          4
         1 070001005366F240         38          3        167          5          1            1          2          2          4          4
         1 07000100537DAA60        167          5        167
         2 070001005383F740        196         43        167          5          1            1          1          3          4          4
         2 07000100536D3F20         67          9        167          5          1            1          1          4          4          4
         2 07000100536168E0          5          5        167          5          1            1          2          3          4          4
         2 07000100536784E0         35        113        167          5          1            1          2          4          4          4
9 rows selected.

很显然,并行查询的4个进程已经分布到两个节点上同时执行了,每个节点上创建4个并行从属进程。

案例解析

背景

客户在使用parallel 10后,数据库未按照指定的并行度10,生成进程,RAC双节点生产大概300多个进程,相关主SQL如下。
image

分析

上述SQL语法问题

官方对于这个parallel的hint定义如下:

For a statement-level PARALLEL hint:

  • PARALLEL: The statement always is run parallel, and the database computes the degree of parallelism, which can be 2 or greater.
  • PARALLEL (DEFAULT): The optimizer calculates a degree of parallelism equal to the number of CPUs available on all participating instances times the value of the PARALLEL_THREADS_PER_CPU initialization parameter.
  • PARALLEL (AUTO): The database computes the degree of parallelism, which can be 1 or greater. If the computed degree of parallelism is 1, then the statement runs serially.
  • PARALLEL (MANUAL): The optimizer is forced to use the parallel settings of the objects in the statement.
  • PARALLEL (integer): The optimizer uses the degree of parallelism specified by integer.
    In the following example, the optimizer calculates the degree of parallelism. The statement always runs in parallel.
SELECT /*+ PARALLEL */ last_name
  FROM employees;

In the following example, the optimizer calculates the degree of parallelism, but that degree may be 1, in which case the statement will run serially.

SELECT /*+ PARALLEL (AUTO) */ last_name
  FROM employees;

In the following example, the PARALLEL hint advises the optimizer to use the degree of parallelism currently in effect for the table itself, which is 5:

CREATE TABLE parallel_table (col1 number, col2 VARCHAR2(10)) PARALLEL 5; 

SELECT /*+ PARALLEL (MANUAL) */ col2
  FROM parallel_table;

上述代码通过 select /*+ parallel 10*/,目的是想实现开10个并行进行查询,正确写法为select /*+ parallel (10)*/,由于语法错误,数据库识别到的可能为select /*+ parallel */,这样并行是开了,但是有系统自己决定并行度,本案例为RAC,节点并行度为 PARALLEL_THREADS_PER_CPU *CPU_COUNT * 可用实例数。

正确写法

image

相关视图

image

作者:bicewow —— bicewow

出处:http://www.cnblogs.com/bicewow/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

原文地址:https://www.cnblogs.com/bicewow/p/14917096.html