메뉴 건너뛰기

bysql.net

1. 기본 개념

2011.06.28 09:09

멋진넘 조회 수:13385

Chapter 7.병렬처리

 

주요내용
1)Query Coodinator(QC)와 병렬 서버 프로세스
2)Intra-Operation Parallelism과 Inter-Operation Parallelism
3)테이블 큐(TQ)
4)IN-OUT Operation
5)Data 재분배
6)Granule
7)병렬 처리 과정에서 발생하는 대기 이벤트

 

 

병렬 처리란, SQL문이 수행해야 할 작업 범위를 여러 개의 작은 단위로 나누어 여러 프로세스(또는 쓰레드)가
동시에 처리하는 것을 말한다. 당연히 여러 프로세스가 동시에 작업하므로 대용량 Data를 처리할 때 수행속도를
극적으로 단축시킬 수가 있다.
생성할 수 있는 최대 병렬 서버 개수는 parallel_max_servers에 의해 결정됨
스터디 할 순서 또한 PLAN 테이블에서의 Name, TQ, IN-OUT, PQ Distrib 임

 

-------------------------------------------------------------------------------------------------------------------
| Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------
(중간생략...)

 

사용방법
1. Hint를 이용한 방법 - /*+ PARALLEL(ALIAS, DEGREE) */
   SELECT /*+ ORDERED USE_HASH(D) FULL(D) FULL(E) NOPARALLEL(D) PARALLEL(E 4) */
          COUNT(*)
        , MIN(E.SAL)
        , MAX(E.SAL)
        , AVG(E.SAL)
        , SUM(E.SAL)
     FROM DEPT D
        , EMP  E
    WHERE 1 = 1
      AND D.LOC    = 'CHICAGO'
      AND E.DEPTNO = D.DEPTNO;

   -------------------------------------------------------------------------------------------------------------------
   | Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
   -------------------------------------------------------------------------------------------------------------------
   |   0 | SELECT STATEMENT          |          |     1 |    18 |     7  (15)| 00:00:01 |        |      |            |
   |   1 |  SORT AGGREGATE           |          |     1 |    18 |            |          |        |      |            |
   |   2 |   PX COORDINATOR          |          |       |       |            |          |        |      |            |
   |   3 |    PX SEND QC (RANDOM)    | :TQ10002 |     1 |    18 |            |          |  Q1,02 | P->S | QC (RAND)  |
   |   4 |     SORT AGGREGATE        |          |     1 |    18 |            |          |  Q1,02 | PCWP |            |
   |*  5 |      HASH JOIN            |          |     5 |    90 |     7  (15)| 00:00:01 |  Q1,02 | PCWP |            |
   |   6 |       BUFFER SORT         |          |       |       |            |          |  Q1,02 | PCWC |            |
   |   7 |        PX RECEIVE         |          |     1 |    11 |     4   (0)| 00:00:01 |  Q1,02 | PCWP |            |
   |   8 |         PX SEND HASH      | :TQ10000 |     1 |    11 |     4   (0)| 00:00:01 |        | S->P | HASH       |
   |*  9 |          TABLE ACCESS FULL| DEPT     |     1 |    11 |     4   (0)| 00:00:01 |        |      |            |
   |  10 |       PX RECEIVE          |          |    14 |    98 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
   |  11 |        PX SEND HASH       | :TQ10001 |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
   |  12 |         PX BLOCK ITERATOR |          |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
   |  13 |          TABLE ACCESS FULL| EMP      |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
   -------------------------------------------------------------------------------------------------------------------

 

2. OBJECT 생성시 PARALLEL DEGREE를 이용하여 생성 - HINT를 사용하지 않아도 자동으로 실행
   CREATE TABLE P_EMP PARALLEL 4
   AS
   SELECT * FROM EMP;

   SELECT /*+ ORDERED USE_HASH(D) FULL(D) FULL(E) */
          COUNT(*)
        , MIN(E.SAL)
        , MAX(E.SAL)
        , AVG(E.SAL)
        , SUM(E.SAL)
     FROM DEPT   D
        , P_EMP  E
    WHERE 1 = 1
      AND D.LOC    = 'CHICAGO'
      AND E.DEPTNO = D.DEPTNO;

   -------------------------------------------------------------------------------------------------------------------
   | Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
   -------------------------------------------------------------------------------------------------------------------
   |   0 | SELECT STATEMENT          |          |     1 |    18 |     7  (15)| 00:00:01 |        |      |            |
   |   1 |  SORT AGGREGATE           |          |     1 |    18 |            |          |        |      |            |
   |   2 |   PX COORDINATOR          |          |       |       |            |          |        |      |            |
   |   3 |    PX SEND QC (RANDOM)    | :TQ10002 |     1 |    18 |            |          |  Q1,02 | P->S | QC (RAND)  |
   |   4 |     SORT AGGREGATE        |          |     1 |    18 |            |          |  Q1,02 | PCWP |            |
   |*  5 |      HASH JOIN            |          |     5 |    90 |     7  (15)| 00:00:01 |  Q1,02 | PCWP |            |
   |   6 |       BUFFER SORT         |          |       |       |            |          |  Q1,02 | PCWC |            |
   |   7 |        PX RECEIVE         |          |     1 |    11 |     4   (0)| 00:00:01 |  Q1,02 | PCWP |            |
   |   8 |         PX SEND HASH      | :TQ10000 |     1 |    11 |     4   (0)| 00:00:01 |        | S->P | HASH       |
   |*  9 |          TABLE ACCESS FULL| DEPT     |     1 |    11 |     4   (0)| 00:00:01 |        |      |            |
   |  10 |       PX RECEIVE          |          |    14 |    98 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
   |  11 |        PX SEND HASH       | :TQ10001 |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
   |  12 |         PX BLOCK ITERATOR |          |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
   |  13 |          TABLE ACCESS FULL| P_EMP    |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
   -------------------------------------------------------------------------------------------------------------------

 

3. 오라클 모니터링과 관련해서..
   ▶DB에서 병렬과 관련된 PROCESS
   DROP   TABLE YHN_EMP;
  
   CREATE TABLE YHN_EMP AS
   SELECT *
     FROM EMP
        , (
          SELECT ROWNUM NO
            FROM DUAL
          CONNECT BY LEVEL <= 100000
          );
  
   -- SESSION 1
   SELECT /*+ ORDERED USE_HASH(D) FULL(D) FULL(E) NOPARALLEL(D) PARALLEL(E 4) */
          COUNT(*)
        , MIN(E.SAL)
        , MAX(E.SAL)
        , AVG(E.SAL)
        , SUM(E.SAL)
     FROM DEPT     D
        , YHN_EMP  E
    WHERE 1 = 1
      AND D.LOC    = 'CHICAGO'
      AND E.DEPTNO = D.DEPTNO;

   -- SESSION2
   SELECT DECODE(A.QCSERIAL#, NULL, 'PARENT', 'CHILD') ST_LVL
        , A.SERVER_SET "SET"
        , A.SID
        , A.SERIAL#
        , STATUS
        , EVENT
        , WAIT_CLASS
     FROM V$PX_SESSION  A
        , V$SESSION     B
    WHERE A.SID   = B.SID
    ORDER BY A.QCSID, ST_LVL DESC, A.SERVER_GROUP, A.SERVER_SET ;

 

   ▶DATABASE에서 병렬과 관련된 PROCESS 찾는 방법
   ST_LVL        SET         SID   SERIAL# STATUS   EVENT                       WAIT_CLASS                 
   ------ ---------- ---------- ---------- -------- --------------------------- ----------------------------
   PARENT                    22      13498 ACTIVE   PX Deq Credit: send blkd     Idle
   CHILD           1        141      53200 ACTIVE   PX Deq: Table Q Normal       Idle
   CHILD           1         13      39600 ACTIVE   PX Deq Credit: send blkd     Idle
   CHILD           1         26      37981 ACTIVE   PX Deq: Table Q Normal       Idle

  

   ▶OS에서 병렬과 관련된 PROCESS 찾는 방법
   bysqldba@ora:~$ ps -ef | grep ora_p | grep -v grep
   oracle   19782     1  0 Apr26 ?        00:02:30 ora_pmon_orcl
   oracle   19794     1  0 Apr26 ?        00:02:24 ora_psp0_orcl
   oracle   25965     1  0 15:46 ?        00:00:00 ora_p000_orcl
   oracle   25967     1  0 15:46 ?        00:00:00 ora_p001_orcl
   oracle   25969     1  0 15:46 ?        00:00:00 ora_p002_orcl
   oracle   26029     1  0 15:48 ?        00:00:00 ora_p003_orcl
   oracle   26031     1  0 15:48 ?        00:00:00 ora_p004_orcl
   oracle   26033     1  0 15:48 ?        00:00:00 ora_p005_orcl

 

1)Query Coodinator(QC)와 병렬 서버 프로세스

 


 

  QC는 병력 SQL문을발행한 세션을 말하고, 병렬 서버 Process는 실제 작업을 수행하는 개별 Session들을 말한다.

  SELECT /*+ ORDERED USE_HASH(D) FULL(D) FULL(E) NOPARALLEL(D) PARALLEL(E 4) */
         COUNT(*)
       , MIN(E.SAL)
       , MAX(E.SAL)
       , AVG(E.SAL)
       , SUM(E.SAL)
    FROM DEPT D
       , EMP  E
   WHERE 1 = 1
     AND D.LOC    = 'CHICAGO'
     AND E.DEPTNO = D.DEPTNO;

  -------------------------------------------------------------------------------------------------------------------
  | Id  | Operation                 | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
  -------------------------------------------------------------------------------------------------------------------
  |   0 | SELECT STATEMENT          |          |     1 |    18 |     7  (15)| 00:00:01 |        |      |            |
  |   1 |  SORT AGGREGATE           |          |     1 |    18 |            |          |        |      |            |
  |   2 |   PX COORDINATOR          |          |       |       |            |          |        |      |            |
  |   3 |    PX SEND QC (RANDOM)    | :TQ10002 |     1 |    18 |            |          |  Q1,02 | P->S | QC (RAND)  |
  |   4 |     SORT AGGREGATE        |          |     1 |    18 |            |          |  Q1,02 | PCWP |            |
  |*  5 |      HASH JOIN            |          |     5 |    90 |     7  (15)| 00:00:01 |  Q1,02 | PCWP |            |
  |   6 |       BUFFER SORT         |          |       |       |            |          |  Q1,02 | PCWC |            |
  |   7 |        PX RECEIVE         |          |     1 |    11 |     4   (0)| 00:00:01 |  Q1,02 | PCWP |            |
  |   8 |         PX SEND HASH      | :TQ10000 |     1 |    11 |     4   (0)| 00:00:01 |        | S->P | HASH       |
  |*  9 |          TABLE ACCESS FULL| DEPT     |     1 |    11 |     4   (0)| 00:00:01 |        |      |            |
  |  10 |       PX RECEIVE          |          |    14 |    98 |     2   (0)| 00:00:01 |  Q1,02 | PCWP |            |
  |  11 |        PX SEND HASH       | :TQ10001 |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | P->P | HASH       |
  |  12 |         PX BLOCK ITERATOR |          |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
  |  13 |          TABLE ACCESS FULL| EMP      |    14 |    98 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
  -------------------------------------------------------------------------------------------------------------------

 

QC(Query Coodinator)의 역할
  1. 병렬 SQL이 시작되면 QC는 사용자가 지정한 PARALLEL 개수와 오퍼레이션 종류에 따라 하나 또는 두 개의

     병렬 서버 집합을 할당. 우선 서버 풀(parallel_min_servers 파라미터로 설정된 만큼의 병렬 프로세스를 오라클이

     기본적으로 생성해 서버 풀에 담아 둠. 교재참조)로부터 필요한 만큼 서버 프로세스를 확보하고, 부족분은 새로 생성함
  2. QC는 각 병렬 서버에게 작업을 할당하고 관리 감독.
  3. 병렬로 처리하도록 사용자가 지시하지 않은 테이블은 QC가 직접 처리함.[예제에선 DEPT 테이블]
     아래의 실행계획에서 DEPT 테이블을 직렬로 읽어 병렬 서버에 전송하는 8~9번 오퍼레이션은 QC 몫
  4. QC는 각 병렬 서버로부터의 산출물을 통합하는 작업을 수행함.
     예를 들어, 위의 실행계획에서 집계 함수를 수행할 때 각 병렬 서버가 자신의 처리 범위 내에서 집계(Id-4)한 값을

     QC에게 전송(Id-3)하면, QC가 최종 집계(Id-1)을 한다.
  5. QC는 쿼리의 최종 결과집합을 사용자에게 전송하며, DML일 경우 갱신 건수를 집계해서 전송.

     전송 단계에서는 스칼라 서브쿼리도 QC가 수행
 
  결과적으로 병렬 SQL의 시작, 수행, 결과전송 모든 프로세스 담당함
  병렬 처리에서 실제 QC 역할을 담당하는 프로세스는 SQL문을 발행한 사용자 세션 자신이다.

 

2)Intra-Operation Parallelism과 Inter-Operation Parallelism
  SELECT /*+ FULL(고객) PARALLEL(고객 4) */
         *
    FROM 고객
   ORDER BY 고객명;

 

 

  ▶8명의 영업사원이 각자 관리하던 명함을 영업팀에서 통합 관리할 목적으로 명함 전체를 이름순으로 정렬하는 경우,
   두 가지 방법을 고려해 볼 수 있음.
 
  ▶첫번째는 8명 각자 자신의 것을 정렬하고 이를 영업팀장이 최종적으로 Merge하는 방법이 있다.
   두번째는 2개조로 나누고 역할을 분담해 서로 다른 작업을 동시에 진행하는 것인데, 영업팀장은 관리를(QC) 하고,
   4명은 분배, 4명은 분배된 내용을 정렬하는 방법이다.
 
  ▶정렬팀은 먼저 알파벳 순으로 1/4로 배분을 받고(A~G, H~M, N~S, T~Z), 분배팀은 QC로부터 할당받은 뭉치를 정렬팀에게
   보내서, 결과적으로 정렬팀이 자신의 분배범위 내에서만 정렬하고, 최종적으로 영업팀장(QC)은 이 4개만 MERGE하면 됨
  
  ▶첫 번째 방법은 작업자가 많을수록 최종 QC가 머지하는 단계에서 부하가 걸리므로, 오라클은 ORDER BY일 경우 
   두 번째 방식을 사용
 
  이때, 배타적인 범위를 독립적으로 동시에 처리하는 것을 [Intra-Operation Parallelism]이라고 함
  위이 예시에서 분배하는 작업과 정렬하는 작업 모두 여기에 해당함. 즉 같은 조끼리는 서로 Data를 주고 받을 일이 없음
 
  반면, 명함을 읽어 상대편 조(다른 서버집합)에 분배하거나 정렬된 결과를 영업팀장(QC)에게 전송하는 작업을 병렬로
  동시에 진행하는 것을 [Inter-Operation Parallelism]라고 함. 이때는 항상 Process간 통신이 발생함

 

3)테이블 큐(TQ)
  1.TQ는 Process간의 Data를 주고받는 기능을 한다.(★★★)
  2.하나의 TQ는 여러 개의 Parallel Slave를 가진다.
  3.TQ는 PQ 수행시 생성된다. 

  ▶PLAN상에 :TQ10000, :TQ10001... 이런 형태의 이름을 [테이블 큐 식별자(TQ Identifier)]라고 한다.

  SELECT /*+ ORDERED USE_HASH(D) FULL(D) FULL(E) NOPARALLEL(D) PARALLEL(E 2)

             PQ_DISTRIBUTE(E BROADCAST NONE) */
         *
    FROM DEPT D
       , EMP  E
   WHERE 1 = 1
     AND E.DEPTNO = D.DEPTNO
   ORDER BY E.ENAME;
 
  --------------------------------------------------------------------------------------------------------------------
  | Id  | Operation                  | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
  --------------------------------------------------------------------------------------------------------------------
  |   0 | SELECT STATEMENT           |          |    14 |   812 |     8  (25)| 00:00:01 |        |      |            |
  |   1 |  PX COORDINATOR            |          |       |       |            |          |        |      |            |
  |   2 |   PX SEND QC (ORDER)       | :TQ10002 |    14 |   812 |     8  (25)| 00:00:01 |  Q1,02 | P->S | QC (ORDER) |
  |   3 |    SORT ORDER BY           |          |    14 |   812 |     8  (25)| 00:00:01 |  Q1,02 | PCWP |            |
  |   4 |     PX RECEIVE             |          |    14 |   812 |     7  (15)| 00:00:01 |  Q1,02 | PCWP |            |
  |   5 |      PX SEND RANGE         | :TQ10001 |    14 |   812 |     7  (15)| 00:00:01 |  Q1,01 | P->P | RANGE      |
  |*  6 |       HASH JOIN            |          |    14 |   812 |     7  (15)| 00:00:01 |  Q1,01 | PCWP |            |
  |   7 |        BUFFER SORT         |          |       |       |            |          |  Q1,01 | PCWC |            |
  |   8 |         PX RECEIVE         |          |     4 |    80 |     4   (0)| 00:00:01 |  Q1,01 | PCWP |            |
  |   9 |          PX SEND BROADCAST | :TQ10000 |     4 |    80 |     4   (0)| 00:00:01 |        | S->P | BROADCAST  |
  |  10 |           TABLE ACCESS FULL| DEPT     |     4 |    80 |     4   (0)| 00:00:01 |        |      |            |
  |  11 |        PX BLOCK ITERATOR   |          |    14 |   532 |     2   (0)| 00:00:01 |  Q1,01 | PCWC |            |
  |  12 |         TABLE ACCESS FULL  | EMP      |    14 |   532 |     2   (0)| 00:00:01 |  Q1,01 | PCWP |            |
  --------------------------------------------------------------------------------------------------------------------
  
  Predicate Information (identified by operation id):
  ---------------------------------------------------
     6 - access("E"."DEPTNO"="D"."DEPTNO")
 
  ▶PQ_DISTRIBUTE HINT : p717 참조

  
  그림 7-3을 보면 쿼리 서버 집합 간(P→P) Inter-Operation Parallelism이 발생할 때는 사용자가 지정한 병렬도

  (위에선 2)의 배수(2*2 = 4)만큼 서버 프로세스가 필요한 것을 알 수 있다.

  또한 TQ에는 병렬도의 제곱만큼 파이프 라인이 필요함
  (그림 7-2에선 병렬도가 4이므로 8(4*2)개의 서버 프로세스를 위해 16(4의 제곱)개의  파이프 라인이 형성되어 있음)
 
  3.1)생산자 / 소비자 모델
      - TQ에는 항상 생산자(Producer)와 소비자(Consumer)가 존재함.
      - 그림 7-3을 보면, 처음 DEPT 테이블을 읽어 분배하는 :TQ10000에서는 QC가 생산자, 서버집합 1이 소비자
      - 두번째 테이블 큐 :TQ10001에서는 서버 집합 1이 생산자, 서버집합 2가 소비자
      - 마지막으로, 정렬된 최종 결과집합을 전송하는 :TQ10002에서는 서버집합 2가 생산자, QC가 소비자
      - SELECT문장에서의 최종 소비자는 항상 QC임
 
  3.2)병렬 실행계획에서 생산자와 소비자 식별(위 SQL 계속)

 


      - 실행계획을 가지고 설명하면, 생산자는 'PX SEND', 소비자는 'PX RECEIVE'가 표시됨
      - 생산자로부터 소비자로 Data 재분배가 일어날 때마다 [Name] 컬럼에 테이블 큐(:TQxxxxx형태)가 새롭게 표시됨
      - 설명(교재 참조)
        ① QC가 DEPT 테이블을 읽어 첫번째 서버집합(Q1, 01)에게 전송 : Id 9~10
        ② 첫 번째 서버집합(Q1,01)은 EMP 테이블을 병렬로 읽으면서 앞서 QC에게서 받아둔 DEPT 테이블과 조인
           조인에 성공한 레코드는 바로바로 두 번째 서버집합(Q1, 02)에게 전송 : Id 5~12
        ③ 마지막으로, 두 번째 서버집합(Q1, 02)은 전송받은 레코드를 정렬 후 나서 QC에게 전송 :Id 2~12

 

4)IN-OUT 오퍼레이션
  모두 5개의 Operation이 있음(각 주요내용은 교재 참조)
 
  ①S→P : PARALLEL_FROM_SERIAL
          ▶QC가 읽은 데이터를 테이블 큐를 통해 병렬 서버 프로세스에게 전송 
          ▶병렬 조인시 DEGREE를 표시하지 않은 쪽에서 발생(병렬 오퍼레이션이 아님)

  ②P→S : PARALLEL_TO_SERIAL
          ▶각 병렬 서버 프로세스가 처리한 데이터틀 QC에게 전송
          ▶병렬 프로세스로부터 QC로 통신이 발생하므로 Inter-Operation Parallelism에 속함

  ③P→P : PARALLEL_FROM_PARALLEL 
          ▶해당 오퍼레이션을 두 개의 서버집합이 처리함을 의미
          ▶두 개의 서버집합간 통신이 발생하므로 Inter-Operation Parallelism에 속함
 
  ④PCWP : PARALLEL_COMBINE_WITH_PARENT 
          ▶한 서버집합이 현재 스텝과 그 부모(Parent) 스텝을 모두 처리함을 의미
          ▶병렬 오퍼레이션이지만 한 서버 집합 내에서는 프로세스 간 통신이 발생하지 않으므로

           Intra-Operation Parallelism에 속함
 
  ⑤PCWC : PARALLEL_COMBINE_WITH_CHILD 
          ▶한 서버집합이 현재 스텝과 그 자식(Child) 스텝을 모두 처리함을 의미
          ▶병렬 오퍼레이션이지만 한 서버 집합 내에서는 프로세스 간 통신이 발생하지 않으므로

           Intra-Operation Parallelism에 속함
 
  정리
  ▶S→P, P→S, P→P는 프로세스 간 통신이 발생한다(Inter-Operation Parallelism)

  ▶PCWP와 PCWC는 프로세스 간 통신이 발생하지 않으며(Intra-Operation Parallelism), 
   각 병렬 서버가 독립적으로 여러 스템을 처리할 때 나타나고 하위 스템의 출력 값이 상위 스텝의 입력 값으로 사용됨

  ▶P→P, P→S, PCWP, PCWC는 병렬 오퍼레이션, S→P는 직렬(Serial) 오퍼레이션임
 
  주의사항
  병렬 쿼리 실행계획에 S→P가 나타난다면 해당 오퍼레이션이 병목 지점인지 의심해 볼 필요가 있음
  만약 처리할 데이터량이 수백 MB이상 된다면 병렬 오퍼레이션으로 바꾸는 것을 고려해야 한다.

 

5)데이터 재분배(PQ Distrib)
  ①RANGE
    ▶ORDER BY 또는 GROUP BY를 병렬로 처리할 때 사용
    ▶데이터를 읽는 첫 번째 서버 집합이 두 번째 서버 집합의 정해진 프로세스에게 [정렬된 키 값에 따라] 분배하는 방식
 

  ②HASH
    ▶조인이나 HASH GROUP BY를 병렬로 처리할 때 사용. 조인 키나 GROUP BY 키 값을 해시함수에 적용하고 리턴 값에

     따라 분배하는 방식
    ▶P→P 뿐만 아니라, S→P 방식으로 이루어 질 수도 있음
   
  ③BROADCAST
    ▶QC 또는 첫 번째 서버 집합에 속한 프로세스들이 각각 읽은 데이터를 두 번째 서버 집합에 속한 "모든"

     병렬 프로세스에게 전송하는 방식
    ▶병렬 조인에서 크기가 매우 작은 테이블이 있을 때 사용되며, P→P 뿐만 아니라, S→P 방식으로 이루어 짐
     (작은 테이블은 병렬로 읽지 않을 때가 많으므로 오히려 S→P이 일반적임)
   
  ④KEY
    ▶특정 컬럼 기준으로 테이블 또는 인덱스를 파티셔닝할 때 사용하는 분배 방식
    ▶Chapter 6의 Partition에 나타나는 Pstart/Pstop의 KEY와는 다름
   
  ⑤ROUND-ROBIN
    ▶파티션 키, 정렬 키, 해시 함수 등에 의존하지 않고 반대편 병렬 서버에 무작위로 데이터를 분배하는 방식
    ▶병렬 INSERT, UPDATE, DELETE할 때 나타남
    ▶무작위라고는 하지만 골고루 분배되도록 함
 
6)Granule
  데이터를 병렬로 처리할 때 일의 최소 단위를 'Granule'이라고 하며, 병렬 서버는 한 번에 하나의 Granule씩만 처리함
  Granule 개수와 크기는 병렬도와 관련 있으며, 이는 병렬 서버 사이에 일을 고르게 분배하는 데 큰 영향을 미침

 

  [블록 기반 Granule]과 [파티션 기반 Granule]이 있는데, 이는 오라클 데이터베이스의 내부적인 결정사항이며

  사용자가 그 크기나 종류를 직접 선택할 수는 없다.

 

  6.1) 블럭 기반 Granule
       ▶블록 기반 Granule은 파티션 테이블 여부와 상관없이 대부분의 병렬 오퍼레이션에 적용되는 기본 작업 단위
       ▶실행계획 상에서는 'PX BLOCK ITERATOR'라고 표시

 

       CREATE UNIQUE INDEX P_DEPT_UX ON P_DEPT(DEPTNO) LOCAL;
       CREATE        INDEX P_EMP_SAL  ON P_EMP(SAL) LOCAL;
       CREATE        INDEX P_EMP_DEPTNO ON P_EMP(DEPTNO) LOCAL;
      
       SELECT /*+ ORDERED USE_HASH(D) FULL(D) FULL(E) PARALLEL(E, 2) */
              *
         FROM P_DEPT  D
            , P_EMP   E
        WHERE 1 = 1
          AND E.DEPTNO = D.DEPTNO;
       -------------------------------------------------------------------------------------------
       | Id  | Operation                 | Name     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
       -------------------------------------------------------------------------------------------
       |   0 | SELECT STATEMENT          |          |       |       |        |      |            |
       |   1 |  PX COORDINATOR           |          |       |       |        |      |            |
       |   2 |   PX SEND QC (RANDOM)     | :TQ10001 |       |       |  Q1,01 | P->S | QC (RAND)  |
       |   3 |    NESTED LOOPS           |          |       |       |  Q1,01 | PCWP |            |
       |   4 |     BUFFER SORT           |          |       |       |  Q1,01 | PCWC |            |
       |   5 |      PX RECEIVE           |          |       |       |  Q1,01 | PCWP |            |
       |   6 |       PX SEND BROADCAST   | :TQ10000 |       |       |        | S->P | BROADCAST  |
       |   7 |        PARTITION RANGE ALL|          |     1 |     4 |        |      |            |
       |   8 |         TABLE ACCESS FULL | P_DEPT   |     1 |     4 |        |      |            |
       |   9 |     PX BLOCK ITERATOR     |          |   KEY |   KEY |  Q1,01 | PCWC |            |
       |* 10 |      TABLE ACCESS FULL    | P_EMP    |   KEY |   KEY |  Q1,01 | PCWP |            |
       -------------------------------------------------------------------------------------------

 

  6.2) 파티션 기반 Granule
       ▶파티션 기반 Granule이 사용될 때, 각 병렬 서버 프로세스는 할당받은 테이블(또는 인덱스)의 파티션 전체를 처리
       ▶실행계획 상에서는 'PX PARTITION RANGE ALL' 또는 'PX PARTITION RANGE ITERATOR'라고 표시됨
       ▶파티션 기반 Granule은 아래와 같은 작업 수행시 사용
        ①Partition-Wise 조인 - 아래 테스트 
        ②파티션 인덱스를 병렬로 스캔할 때 
        ③파티션 인덱스를 병렬로 갱신할 때 
        ④9iR1 이전에서의 병렬 DML 
        ⑤파티션 테이블 또는 파티션 인덱스를 병렬로 생성할 때

 

       SELECT /*+ ORDERED USE_NL(D) FULL(D) INDEX(E, P_EMP_SAL)
                  PARALLEL_INDEX(E, P_EMP_SAL, 2) */
              *
         FROM P_EMP   E
            , P_DEPT  D
        WHERE 1 = 1
          AND E.DEPTNO = D.DEPTNO
          AND E.SAL    > 1000;
       ----------------------------------------------------------------------------------------
       | Id  | Operation                             | Name      |    TQ  |IN-OUT| PQ Distrib |
       ----------------------------------------------------------------------------------------
       |   0 | SELECT STATEMENT                      |           |        |      |            |
       |   1 |  PX COORDINATOR                       |           |        |      |            |
       |   2 |   PX SEND QC (RANDOM)                 | :TQ10000  |  Q1,00 | P->S | QC (RAND)  |
       |   3 |    NESTED LOOPS                       |           |  Q1,00 | PCWP |            |
       |   4 |     PX PARTITION RANGE ALL            |           |  Q1,00 | PCWC |            |
       |   5 |      TABLE ACCESS BY LOCAL INDEX ROWID| P_EMP     |  Q1,00 | PCWP |            |
       |*  6 |       INDEX RANGE SCAN                | P_EMP_SAL |  Q1,00 | PCWP |            |
       |   7 |     PARTITION RANGE ITERATOR          |           |  Q1,00 | PCWP |            |
       |*  8 |      TABLE ACCESS FULL                | P_DEPT    |  Q1,00 | PCWP |            |
       ----------------------------------------------------------------------------------------

 

7)병렬 처리과정에서 발생하는 대기 이벤트
  ▶병렬 처리 과정에서 자주 발생하는 대기 이벤트 요약
  --------------------------------------------------------------------------------------------------------------
  이벤트명                     | 클래스 | 설명
  --------------------------------------------------------------------------------------------------------------
  PX Deq: Execute Reply        | Idle   | QC가 각 병렬 서버에게 작업을 배분후 작업이 완료되기를 기다리는 상태
  --------------------------------------------------------------------------------------------------------------
  PX Deq: Execute Msg          | Idle   | ▶병렬 서버가 자신의 임무를 완수하고서 다른 병렬 서버가 일을 마치기를
                               |        |  기다리는 상태
                               |        | ▶QC 또는 소비자 병렬 서버에게 데이터 전송을 완료했을 때 나타남 
  --------------------------------------------------------------------------------------------------------------
  PX Deq: Table Q Normal       | Idle   | 메세지 수신 대기. 메세지 큐에 데이터가 쌓이기를 기다리는 상태.
  --------------------------------------------------------------------------------------------------------------
  PX Deq Credit: send blkd     | Other  | ▶메세지 송신 대기
                               |        | ▶QC 또는 소비자 병렬 서버에게 전송할 데이터가 있는데 블로킹 된 상태
                               |        | ▶생산자 프로세스가 메세지 큐를 통해 데이터를 전송하려고 하는데 어떤
                               |        |  이유에서건 소비자 프로세스가 버퍼에서 데이터를 빨리 꺼내가지 않을 때
                               |        |  발생함
  --------------------------------------------------------------------------------------------------------------
  PX Deq Credit: need bulffer  | Idle   | ▶데이터를 전송하기 전에 상대편 병렬 서버 또는 QC로부터 credit 비트를
                               |        |  얻으려고 대기하는 상태
                               |        | ▶오라클 측의 설명(메타링크 문서번호 271767.1)에 의하면
                               |        |  'PX Deq Credit:send blkd'와 'PX Deq Credit: need bulffer'는 거의 같은
                               |        |  대기 이벤트이고, 내부적인 이유로 전자는 로컬 시스템에서 자주 발생하며
                               |        |  후자는 RAC 시스템에서 자주 발생한다고 함
  --------------------------------------------------------------------------------------------------------------

  위의 이벤트는 실시간으로 계속적으로 바뀜.

  
  7.1)대기 이벤트 모니터링 : 죄송합니다...
  7.2)대기 이벤트 해소 : 죄송합니다...