☞ 병렬 조인 메커니즘의 핵심은, 병렬 프로세스들이 서로 독립적으로 조인을 수행할 수 있도록 데이터를 분배하는데 있음.
☞ 분배작업이 완료되고 나면 프로세스 간에 서로 방해 받지 않고 각자 할당받은 범위 내애서 조인을 완료
☞ 병렬 조인 방식
1. 파티션 방식 : Partition-Pair끼리 조인 수행
1-1) 둘 다 같은 기준으로 파티셔닝(equi-partitioning)된 경우
1-2) 둘 중 하나만 파티셔닝된 경우(둘 다 파티셔닝되었더라도 파티션 기준이 서로 다른 경우도 해당)
1-3) 둘 다 파티셔닝되지 않은 경우
2. Broadcase 방식 : 한쪽 테이블을 Broadcase하고 나서 조인 수행(파티셔닝 불필요)
-- 오라클 버전
SELECT * FROM v$version
;
BANNER
------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit
PL/SQL Release 10.2.0.3.0 - Production
-- EMP, DEPT 파티션 테이블 생성
DROP TABLE USER.EMP;
DROP TABLE USER.DEPT;
CREATE TABLE EMP
(EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(2))
PARTITION BY HASH (DEPTNO)
(
PARTITION PH_DEPTNO_001,
PARTITION PH_DEPTNO_002,
PARTITION PH_DEPTNO_003,
PARTITION PH_DEPTNO_004
);
INSERT INTO EMP VALUES
(7369, 'SMITH', 'CLERK', 7902,
TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
INSERT INTO EMP VALUES
(7499, 'ALLEN', 'SALESMAN', 7698,
TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);
INSERT INTO EMP VALUES
(7521, 'WARD', 'SALESMAN', 7698,
TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);
INSERT INTO EMP VALUES
(7566, 'JONES', 'MANAGER', 7839,
TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP VALUES
(7654, 'MARTIN', 'SALESMAN', 7698,
TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP VALUES
(7698, 'BLAKE', 'MANAGER', 7839,
TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP VALUES
(7782, 'CLARK', 'MANAGER', 7839,
TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP VALUES
(7788, 'SCOTT', 'ANALYST', 7566,
TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7839, 'KING', 'PRESIDENT', NULL,
TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP VALUES
(7844, 'TURNER', 'SALESMAN', 7698,
TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30);
INSERT INTO EMP VALUES
(7876, 'ADAMS', 'CLERK', 7788,
TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP VALUES
(7900, 'JAMES', 'CLERK', 7698,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);
INSERT INTO EMP VALUES
(7902, 'FORD', 'ANALYST', 7566,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7934, 'MILLER', 'CLERK', 7782,
TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);
CREATE TABLE DEPT
(DEPTNO NUMBER(2),
DNAME VARCHAR2(14),
LOC VARCHAR2(13) )
PARTITION BY HASH (DEPTNO)
(
PARTITION PH_DEPTNO_001,
PARTITION PH_DEPTNO_002,
PARTITION PH_DEPTNO_003,
PARTITION PH_DEPTNO_004
);
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');
COMMIT;
/
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(USER,
'EMP',
CASCADE => TRUE);
END;
/
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(USER,
'DEPT',
CASCADE => TRUE);
END;
/
-- XPLAN 확인
EXPLAIN PLAN FOR
SELECT /*+ LEADING(E D) FULL(D) FULL(E) PARALLEL(D 2) PARALLEL(E 2) PQ_DISTRIBUTE(D, NONE, NONE) */
D.DEPTNO,
D.DNAME,
E.ENAME
FROM DEPT D,
EMP E
WHERE E.DEPTNO = D.DEPTNO
;
@xplan
---------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 308 | 14 (8)| 00:00:01 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 14 | 308 | 14 (8)| 00:00:01 | | | Q1,00 | P->S | QC (RAND) |
| 3 | PX PARTITION HASH ALL| | 14 | 308 | 14 (8)| 00:00:01 | 1 | 4 | Q1,00 | PCWC | |
|* 4 | HASH JOIN | | 14 | 308 | 14 (8)| 00:00:01 | | | Q1,00 | PCWP | |
| 5 | TABLE ACCESS FULL | EMP | 14 | 126 | 7 (0)| 00:00:01 | 1 | 4 | Q1,00 | PCWP | |
| 6 | TABLE ACCESS FULL | DEPT | 4 | 52 | 7 (0)| 00:00:01 | 1 | 4 | Q1,00 | PCWP | |
---------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("E"."DEPTNO"="D"."DEPTNO")
18 rows selected.
-- 그림 7_7 참조
-- 오라클 버전
SELECT * FROM v$version
;
BANNER
------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit
PL/SQL Release 10.2.0.3.0 - Production
-- EMP, DEPT 파티션 테이블 생성
DROP TABLE USER.EMP;
DROP TABLE USER.DEPT;
CREATE TABLE EMP
(EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(2));
INSERT INTO EMP VALUES
(7369, 'SMITH', 'CLERK', 7902,
TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
INSERT INTO EMP VALUES
(7499, 'ALLEN', 'SALESMAN', 7698,
TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);
INSERT INTO EMP VALUES
(7521, 'WARD', 'SALESMAN', 7698,
TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);
INSERT INTO EMP VALUES
(7566, 'JONES', 'MANAGER', 7839,
TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP VALUES
(7654, 'MARTIN', 'SALESMAN', 7698,
TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP VALUES
(7698, 'BLAKE', 'MANAGER', 7839,
TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP VALUES
(7782, 'CLARK', 'MANAGER', 7839,
TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP VALUES
(7788, 'SCOTT', 'ANALYST', 7566,
TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7839, 'KING', 'PRESIDENT', NULL,
TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP VALUES
(7844, 'TURNER', 'SALESMAN', 7698,
TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30);
INSERT INTO EMP VALUES
(7876, 'ADAMS', 'CLERK', 7788,
TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP VALUES
(7900, 'JAMES', 'CLERK', 7698,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);
INSERT INTO EMP VALUES
(7902, 'FORD', 'ANALYST', 7566,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7934, 'MILLER', 'CLERK', 7782,
TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);
CREATE TABLE DEPT
(DEPTNO NUMBER(2),
DNAME VARCHAR2(14),
LOC VARCHAR2(13) )
PARTITION BY HASH (DEPTNO)
(
PARTITION PH_DEPTNO_001,
PARTITION PH_DEPTNO_002,
PARTITION PH_DEPTNO_003,
PARTITION PH_DEPTNO_004
);
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');
COMMIT;
/
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(USER,
'EMP',
CASCADE => TRUE);
END;
/
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(USER,
'DEPT',
CASCADE => TRUE);
END;
/
-- XPLAN 확인
EXPLAIN PLAN FOR
SELECT /*+ LEADING(E D) FULL(D) FULL(E) PARALLEL(D 2) PARALLEL(E 2) PQ_DISTRIBUTE(D, PARTITION, NONE) */
D.DEPTNO,
D.DNAME,
E.ENAME
FROM DEPT D,
EMP E
WHERE E.DEPTNO = D.DEPTNO
;
@xplan
-------------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 308 | 10 (10)| 00:00:01 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 14 | 308 | 10 (10)| 00:00:01 | | | Q1,01 | P->S | QC (RAND) |
|* 3 | HASH JOIN | | 14 | 308 | 10 (10)| 00:00:01 | | | Q1,01 | PCWP | |
| 4 | PX RECEIVE | | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,01 | PCWP | |
| 5 | PX SEND PARTITION (KEY)| :TQ10000 | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,00 | P->P | PART (KEY) |
| 6 | PX BLOCK ITERATOR | | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,00 | PCWC | |
| 7 | TABLE ACCESS FULL | EMP | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,00 | PCWP | |
| 8 | PX PARTITION HASH ALL | | 4 | 52 | 7 (0)| 00:00:01 | 1 | 4 | Q1,01 | PCWC | |
| 9 | TABLE ACCESS FULL | DEPT | 4 | 52 | 7 (0)| 00:00:01 | 1 | 4 | Q1,01 | PCWP | |
-------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("E"."DEPTNO"="D"."DEPTNO")
21 rows selected.
-- 그림 7_8 참조
-- 오라클 버전
SELECT * FROM v$version
;
BANNER
------------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bit
PL/SQL Release 10.2.0.3.0 - Production
-- EMP, DEPT 파티션 테이블 생성
DROP TABLE USER.EMP;
DROP TABLE USER.DEPT;
CREATE TABLE EMP
(EMPNO NUMBER(4) NOT NULL,
ENAME VARCHAR2(10),
JOB VARCHAR2(9),
MGR NUMBER(4),
HIREDATE DATE,
SAL NUMBER(7, 2),
COMM NUMBER(7, 2),
DEPTNO NUMBER(2));
INSERT INTO EMP VALUES
(7369, 'SMITH', 'CLERK', 7902,
TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);
INSERT INTO EMP VALUES
(7499, 'ALLEN', 'SALESMAN', 7698,
TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);
INSERT INTO EMP VALUES
(7521, 'WARD', 'SALESMAN', 7698,
TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);
INSERT INTO EMP VALUES
(7566, 'JONES', 'MANAGER', 7839,
TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);
INSERT INTO EMP VALUES
(7654, 'MARTIN', 'SALESMAN', 7698,
TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);
INSERT INTO EMP VALUES
(7698, 'BLAKE', 'MANAGER', 7839,
TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);
INSERT INTO EMP VALUES
(7782, 'CLARK', 'MANAGER', 7839,
TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);
INSERT INTO EMP VALUES
(7788, 'SCOTT', 'ANALYST', 7566,
TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7839, 'KING', 'PRESIDENT', NULL,
TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);
INSERT INTO EMP VALUES
(7844, 'TURNER', 'SALESMAN', 7698,
TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30);
INSERT INTO EMP VALUES
(7876, 'ADAMS', 'CLERK', 7788,
TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);
INSERT INTO EMP VALUES
(7900, 'JAMES', 'CLERK', 7698,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);
INSERT INTO EMP VALUES
(7902, 'FORD', 'ANALYST', 7566,
TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);
INSERT INTO EMP VALUES
(7934, 'MILLER', 'CLERK', 7782,
TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, 10);
CREATE TABLE DEPT
(DEPTNO NUMBER(2),
DNAME VARCHAR2(14),
LOC VARCHAR2(13) )
PARTITION BY HASH (DEPTNO);
INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK');
INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS');
INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO');
INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');
COMMIT;
/
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(USER,
'EMP',
CASCADE => TRUE);
END;
/
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(USER,
'DEPT',
CASCADE => TRUE);
END;
/
-- XPLAN 확인
EXPLAIN PLAN FOR
SELECT /*+ LEADING(E D) FULL(D) FULL(E) PARALLEL(D 2) PARALLEL(E 2) PQ_DISTRIBUTE(D, HASH, HASH) */
D.DEPTNO,
D.DNAME,
E.ENAME
FROM DEPT D,
EMP E
WHERE E.DEPTNO = D.DEPTNO
;
@xplan
---------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 308 | 6 (0)| 00:00:01 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10002 | 14 | 308 | 6 (0)| 00:00:01 | | | Q1,02 | P->S | QC (RAND) |
|* 3 | HASH JOIN BUFFERED | | 14 | 308 | 6 (0)| 00:00:01 | | | Q1,02 | PCWP | |
| 4 | PX RECEIVE | | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,02 | PCWP | |
| 5 | PX SEND HASH | :TQ10000 | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,00 | P->P | HASH |
| 6 | PX BLOCK ITERATOR | | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,00 | PCWC | |
| 7 | TABLE ACCESS FULL| EMP | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,00 | PCWP | |
| 8 | PX RECEIVE | | 4 | 52 | 3 (0)| 00:00:01 | | | Q1,02 | PCWP | |
| 9 | PX SEND HASH | :TQ10001 | 4 | 52 | 3 (0)| 00:00:01 | | | Q1,01 | P->P | HASH |
| 10 | PX BLOCK ITERATOR | | 4 | 52 | 3 (0)| 00:00:01 | 1 | 1 | Q1,01 | PCWC | |
| 11 | TABLE ACCESS FULL| DEPT | 4 | 52 | 3 (0)| 00:00:01 | 1 | 1 | Q1,01 | PCWP | |
---------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("E"."DEPTNO"="D"."DEPTNO")
EXPLAIN PLAN FOR
SELECT /*+ FULL(D) FULL(E) PARALLEL(D 2) PARALLEL(E 2) */
D.DEPTNO,
D.DNAME,
E.ENAME
FROM DEPT D,
EMP E
WHERE E.DEPTNO = D.DEPTNO
;
@xplan
---------------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | TQ |IN-OUT| PQ Distrib |
---------------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 308 | 6 (0)| 00:00:01 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 14 | 308 | 6 (0)| 00:00:01 | | | Q1,01 | P->S | QC (RAND) |
|* 3 | HASH JOIN | | 14 | 308 | 6 (0)| 00:00:01 | | | Q1,01 | PCWP | |
| 4 | PX RECEIVE | | 4 | 52 | 3 (0)| 00:00:01 | | | Q1,01 | PCWP | |
| 5 | PX SEND BROADCAST | :TQ10000 | 4 | 52 | 3 (0)| 00:00:01 | | | Q1,00 | P->P | BROADCAST |
| 6 | PX BLOCK ITERATOR | | 4 | 52 | 3 (0)| 00:00:01 | 1 | 1 | Q1,00 | PCWC | |
| 7 | TABLE ACCESS FULL| DEPT | 4 | 52 | 3 (0)| 00:00:01 | 1 | 1 | Q1,00 | PCWP | |
| 8 | PX BLOCK ITERATOR | | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,01 | PCWC | |
| 9 | TABLE ACCESS FULL | EMP | 14 | 126 | 3 (0)| 00:00:01 | | | Q1,01 | PCWP | |
---------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("E"."DEPTNO"="D"."DEPTNO")
21 rows selected.
Elapsed: 00:00:00.17
병렬 조인 방식 | 특징 |
---|---|
Full Partition Wise 조인 | ☞ 두 테이블 모두 조인 컬럼에 대해 같은 기준으로 파티셔닝 ☞ 데이터 재분배 불필요 -> 단일 서버 집합만으로 수정 |
Partial Partition Wise 조인 | ☞ 둘 중 한 테이블만 조인 컬럼에 대해 파티셔닝된 경우 ☞ 파티셔닝되지 않은 다른 쪽 테이블을 같은 기준으로 파티셔닝하고 나서 Full Partition Wise 조인 ☞ 동적 파티셔닝을 위한 데이터 재분배 필요 -> 두 개의 서버 집합이 작업 수행 |
동적 파티셔닝 | ☞ 어느 한 쪽도 조인 컬럼에 대해 파티셔닝되지 않은 상황 ☞ 양쪽 테이블이 모두 대용량 ☞ 임시 테이블스페이스를 많이 사용 ☞ 양쪽 테이블 모두 전체범위처리 ☞ 조인 컬럼의 데이터 분포가 균일해야 함 |
Broadcase | ☞ 어느 한 쪽도 조인 컬럼에 대해 파티셔닝되지 않은 상황 ☞ 둘 중 하나의 테이블이 매우 적을 때 ☞ 동적 파티셔닝이 불필요 -> 큰 테이블에 대한 부분범위처리 가능 |