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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM