Post

<오라클 성능 고도화 원리와 해법2> Ch07-03 병렬 조인

오라클 성능 고도화 원리와 해법2 - Ch07-03 병렬 조인

병렬 조인 메커니즘을 이해하는 핵심 원리는 병렬 프로세스들이 서로 독립적으로 조인을 수행할 수 있도록 데이터를 분배하는 데 있다. 분배 작업이 완료되고 나면 프로세스 간에 서로 방해받지 않고 각자 할당받은 범위 내에서 조인을 완료한다.

병렬 조인에는 크게 두 가지 방식이 있다.

  1. 파티션 방식: Partition-Pair끼리 조인 수행
  2. Broadcast 방식: 한쪽 테이블을 Broadcast하고 나서 조인 수행 (파티셔닝 불필요)

1번 파티션 방식은 조인되는 두 테이블의 파티션 상태에 따라 아래 세 가지 경우로 나뉜다.

1-1. 둘 다 같은 기준으로 파티셔닝(equi-partitioning)된 경우 1-2. 둘 중 하나만 파티셔닝된 경우 (둘 다 파티셔닝되었더라도 파티션 기준이 서로 다른 경우는 여기에 해당) 1-3. 둘 다 파티셔닝되지 않은 경우

지금부터 dept와 emp 테이블을 병렬로 조인하는 아래 쿼리를 예로 들면서 각각에 대한 내부 수행 원리를 자세히 살펴보자. 설명하는 순서는 1-1, 1-2, 1-3, 2번 순이다.

1
2
3
4
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

(1) 둘 다 같은 기준으로 파티셔닝된 경우 - Full Partition Wise 조인

앞서 예시한 병렬 조인 문장을 처리하는 데 있어, 조인에 참여하는 두 테이블이 조인 컬럼(deptno)에 대해 같은 기준으로 파티셔닝(equi-partitioning)되어 있다면 병렬 조인은 매우 간단하다.

병렬도가 2라고 가정하면, 그림 7-7에서 보듯 P000과 P001 서버 프로세스가 각각 Partition Pair1과 Partition Pair2를 처리한다. 조인을 수행하는 동안 P000과 P001 프로세스가 데이터를 주고받으며 통신(inter-operation parallelism)할 필요가 전혀 없다. 이미 상호 배타적인 Partition-Pair가 형성되어 있으므로 각 서버 프로세스가 하나씩 독립적으로(intra-operation parallelism) 조인을 수행할 수 있는 것이다.

여기서 기억할 중요한 사실은 다음과 같다.

  • 뒤에서 설명하겠지만, 다른 병렬 조인은 두 개의 서버 집합이 필요한 반면, 여기서는 하나의 서버 집합만 필요하다.
  • Full Partition Wise 조인은 파티션 기반 Granule이므로 서버 프로세스 개수는 파티션 개수 이하로 제한된다.
  • 파티션 방식(Method)은 어떤 것이든 상관없다. Range이든 리스트이든 해시이든 두 테이블이 조인 컬럼에 대해 같은 방식, 같은 기준으로 파티셔닝되어 있다면 서로 방해받지 않고 Partition Pair끼리 독립적인 병렬 조인이 가능하기 때문이다.
  • 조인 방식도 어떤 것이든 선택 가능하다. NL 조인, 소트 머지 조인, 해시 조인 등.

(2) 둘 중 하나만 파티셔닝된 경우 - Partial Partition Wise 조인

둘 중 한 테이블만 조인 컬럼에 대해 파티셔닝된 경우, 다른 한쪽 테이블을 같은 기준으로 동적으로 파티셔닝하고 나서 각 Partition-Pair를 독립적으로 병렬 조인하는 것을 Partial Partition Wise 조인이라고 한다. 둘 다 파티셔닝되었지만 파티션 기준이 서로 다른 경우도 이 방식으로 조인될 수 있다.

중요한 것은, 데이터를 동적으로 파티셔닝하기 위해선 데이터 재분배가 선행되어야 한다는 사실이다. 즉, Inter-operation parallelism을 위해 두 개의 서버 집합이 필요해진다.

그림 7-8은 병렬도가 2인 상황에서 QC를 포함한 5개 프로세스가 어떤 식으로 두 테이블을 조인하는지를 표현한 것이다. (그림에는 각각 그렸지만 1단계 P002, P003 프로세스와 2단계 P002, P003 프로세스는 서로 같은 존재이다.)

(3) 둘 다 파티셔닝되지 않은 경우 - 동적 파티셔닝

조인 컬럼에 대해 어느 한쪽도 파티셔닝되지 않은 상황이라면 오라클은 두 가지 방식 중 하나를 사용한다.

  • 양쪽 테이블을 동적으로 파티셔닝하고서 Full Partition Wise 조인
  • 한쪽 테이블을 Broadcast하고 나서 조인

Broadcast 방식은 바로 뒤에서 설명할 것이며, 여기서는 동적으로 파티셔닝하는 방식에 대해 살펴보자.

그림 7-9는 총 3단계 중 1~2단계를 표현하고 있다(DOP=2).

  • 1단계: 첫 번째 서버 집합(P000, P001)이 dept 테이블을 읽어 두 번째 서버 집합(P002, P003)에 전송한다.
  • 2단계: 첫 번째 서버 집합(P000, P001)이 emp 테이블을 읽어 두 번째 서버 집합(P002, P003)에 전송한다.

그림에는 각각 그렸지만 1단계와 2단계를 처리하는 서버 집합은 서로 같은 존재이다.

첫 번째 서버 집합은 데이터를 분배하는 역할을 하고, 두 번째 서버 집합은 받은 데이터를 파티셔닝하는 역할을 한다. 가능하다면 메모리 내에서 파티셔닝하겠지만 공간이 부족할 때는 Temp 테이블스페이스를 활용할 것이다.

이렇게 2단계까지 완료하고 나면 이제 Partition-Pair가 구성되었으므로 Full Partition Wise 조인을 수행할 수 있게 되었다.

  • 3단계: 양쪽 테이블 모두의 파티셔닝을 담당한 두 번째 서버 집합(P002, P003)이 각 Partition-Pair에 대해 독립적으로 병렬 조인을 수행한다.

3단계를 표현한 그림 7-10이 Full Partition Wise 조인을 표현한 그림 7-7과 같은 그림임을 확인하기 바란다.

이 방식의 특징은, 조인을 본격적으로 수행하기 전 사전 준비 작업 단계에서 메모리 자원과 Temp 테이블스페이스 공간을 많이 사용한다는 데 있다.

그리고 양쪽 모두 파티셔닝해야 하므로 기본적으로 양쪽 테이블 모두에 대한 전체 범위 처리가 불가피하다.

또한 조인 컬럼의 데이터 분포가 균일하지 않을 때는 프로세스 간 일량 차이 때문에 병렬 처리 효과가 크게 반감될 수 있다. 예를 들어, 상품권 업무를 담당하는 사원이 몇몇 사람에게 집중된 상황에서 아래 병렬 쿼리를 이 방식으로 수행한다면 16개 중 일부 프로세스만 열심히 일하고 나머지는 Idle 상태로 대기하는 현상이 발생할 것이다.

1
2
3
select /*+ full(a) full(b) parallel a(16) parallel (b 16) */ a.*, ...
from   사원 a, 상품권 b
where  a.사번 = b.담당자사번

물론 이런 특징은 Partition Wise 조인에서도 똑같이 나타날 수 있다. 하지만 그런 컬럼이라면 애당초 파티션 기준 컬럼으로 부적당한 것이므로 병렬 조인의 비효율보다는 파티션 전략의 오류로 보는 것이 타당하다.

동적으로 파티셔닝해야 하는 상황에서는 위와 같은 현상이 실제 일어날 수 있기 때문에 조인문을 작성할 때 세심한 주의가 필요하다. 사원 테이블이 매우 작다면 이어서 설명할 Broadcast 방식을 사용함으로써 쉽게 문제를 해결할 수 있지만, 그렇지 않다면 아예 병렬 조인을 포기하는 것이 나을 수도 있다.

결론적으로 동적 파티셔닝 방식은, 아래와 같은 상황에서 유용한 병렬 조인 방식이다.

  • 어느 한쪽도 조인 컬럼 기준으로 파티셔닝되지 않은 상황에서
  • 두 테이블 모두 대용량 테이블이고
  • 조인 컬럼의 데이터 분포가 균일할 때

블룸 필터를 활용한 프로세스 간 통신 최소화

병렬 조인을 수행하는 과정에서 발생하는 프로세스 간 통신량을 줄이기 위해 블룸 필터 알고리즘이 사용될 수 있다. 블룸 필터 알고리즘에 대해서는 6장 2절에서 자세히 설명하였다.

Q1, Q2 프로세스들이 emp 테이블을 읽어 Q2 서버 집합에 전송할 때는 먼저 블룸 필터를 탐색한다. 블룸 필터의 비트값이 모두 1로 설정된 deptno일 때만 데이터를 전송하고 나머지는 버린다.

오라클 10g부터 활성화된 이 기능은 bloomfilter_enabled 파라미터를 통해 활성화되며, px_join_filter와 no_px_join_filter 힌트로도 제어할 수 있다.

(4) 둘 다 파티셔닝되지 않은 경우 - Broadcast 방식

조인 컬럼에 대해 어느 한쪽도 파티셔닝되지 않은 상황에서 오라클이 선택할 수 있는 두 번째 방식은 Broadcast 방식이다. 두 테이블 중 작은 쪽을 반대편 서버 집합의 “모든” 프로세스에 Broadcast하고 나서 조인을 수행하는 방식이다.

그림 7-11은 Broadcast 방식의 병렬 조인을 도식화한 것으로, 병렬도는 2라고 가정하였다.

  • 1단계: 첫 번째 서버 집합에 속한 프로세스들이 각자 읽은 dept 테이블 레코드를 두 번째 서버 집합에 속한 모든 병렬 프로세스에게 전송한다.
  • 2단계: 두 번째 서버 집합에 속한 프로세스들이 각자 맡은 범위의 emp 테이블을 읽으면서 병렬로 조인을 수행한다. 1단계가 완료되면 두 번째 서버 집합에 속한 프로세스 모두 dept 테이블의 완전한 집합을 갖게 되므로 프로세스 간 상호 간섭 없이 독립적으로 조인 수행이 가능하다.

양쪽 테이블 모두 파티션되지 않았을 때는 1차적으로 Broadcast 방식이 고려되어야 한다. 양쪽 테이블을 동적으로 파티셔닝하는 방식은 앞서 설명한 것처럼 메모리 자원과 Temp 테이블스페이스 공간을 많이 사용하는 반면, 이 방식은 리소스 사용량이 매우 적기 때문이다.

이런 특징은 Broadcast되는 테이블이 아주 작을 때만 적용된다. 만약 Broadcast되는 테이블이 중대형 이상일 때는 과도한 프로세스 간 통신 때문에 성능이 매우 느려질 수 있다. 뿐만 아니라 두 번째 서버 집합이 메모리 내에서 감당하기 어려울 정도로 큰 테이블을 Broadcast하면 Temp 테이블스페이스 공간을 사용하게 되면서 성능이 심각하게 저하될 것이다.

따라서 그런 부담이 없을 정도로 어느 한쪽 테이블이 충분히 작을 때만 유용하다.

이 외에도 Broadcast 방식이 갖는 특징은 다음과 같다.

  • Broadcast 대상은 작은 집합이어야 하므로 Serial 스캔으로 처리해도 무방하다. 따라서 PP보다 SP 형태가 오히려 일반적이며, 이는 조인되는 두 테이블 중 어느 한쪽 테이블만 병렬로 처리함을 뜻한다.
  • 큰 테이블이라도 조건 필터링을 거친 결과 집합이 작다면 Broadcast 대상이 될 수 있고, 이때는 PP가 유리하다.
  • Broadcast가 이루어지고 나서의 조인 방식은 어떤 것이든 선택 가능하다. NL 조인, 소트머지 조인, 해시 조인 등.
  • Broadcast되는 작은 쪽 테이블은 전체 범위 처리가 불가피하지만, 큰 테이블은 부분 범위 처리가 가능하다.

지금까지 설명한 4가지 병렬 조인 방식의 특징을 요약해보자.

This post is licensed under CC BY 4.0 by the author.