병렬 데이터 분배와 Skew: HASH·BROADCAST·RANGE·Bloom Filter
병렬 Sort·Group·Join에서 Row를 어느 PX Server로 보낼지 결정하는 분배 방식과 불필요한 전송을 줄이는 Bloom Filter를 학습합니다.
핵심 요약
병렬 실행에서는 여러 PX Server가 Table을 나누어 Scan하는 것만으로 충분하지 않습니다. Join·Group By·Order By·Parallel Load처럼 다음 단계가 특정 Key 또는 Partition 기준으로 Row를 처리해야 한다면, Producer PX Server Set이 만든 Row를 알맞은 Consumer PX Server로 다시 배치해야 합니다. 이 과정을 Data Redistribution 또는 PX Data Distribution이라고 합니다.
Producer PX Server Set
→ Row 생성
→ Table Queue를 통해 HASH·BROADCAST·RANGE·PARTITION 등으로 분배
→ Consumer PX Server Set
→ Join·Sort·Aggregate·Load 수행
Data Distribution은 병렬 성능을 좌우하는 핵심 단계입니다. 적절한 분배는 Consumer별 작업량을 비슷하게 만들지만, 부적절한 분배는 Network·Interconnect·Memory·TEMP·Queue Wait를 늘리고 일부 PX Server만 오래 일하는 Skew를 만듭니다. Bloom Filter는 대량 Probe Row가 Join 또는 PX 전송까지 도달하기 전에 확실히 일치하지 않는 Row를 조기에 제거하는 확률적 Membership Filter입니다.
병렬 분배와 Bloom Filter는 SQL의 결과 의미를 바꾸기 위한 기능이 아닙니다. 실제 효과는 실행계획의 TQ·IN-OUT·PQ Distrib, Runtime Row Source 통계, V$PQ_TQSTAT, V$SQL_JOIN_FILTER, SQL Monitor를 함께 사용해 검증해야 합니다.
학습 목표
이 이론을 학습한 뒤에는 다음을 설명할 수 있어야 합니다.
- 병렬 실행에서 Row 재분배가 필요한 이유를 설명한다.
- Join Method와 PX Distribution Method를 구분한다.
- HASH·BROADCAST·RANGE 분배의 동작과 비용을 설명한다.
PARTITION(KEY)분배와 Partition-Wise 처리·Parallel Load의 관계를 설명한다.- HYBRID HASH가 Runtime에 BROADCAST와 HASH 중 하나를 선택하는 원리를 설명한다.
- 실행계획의
PX SEND·PX RECEIVE,TQ,IN-OUT,PQ Distrib을 연결한다. - Producer Skew, Distribution Skew, Join Key Skew, Row Width Skew를 구분한다.
- Bloom Filter의 False Positive·False Negative 특성과 적용 범위를 설명한다.
V$PQ_TQSTAT과V$SQL_JOIN_FILTER로 실제 분배·Filter 효과를 검증한다.PQ_DISTRIBUTE,PQ_SKEW,PX_JOIN_FILTERHint를 제한적인 실험 수단으로 사용한다.
1. 병렬 실행에서 Row를 다시 나누는 이유
다음 Query는 주문과 고객을 고객번호로 조인한 뒤 지역별 금액을 집계합니다.
SELECT c.region,
SUM(o.amount) AS total_amount
FROM customers c
JOIN orders o
ON o.customer_id = c.customer_id
GROUP BY c.region;
ORDERS를 여러 PX Server가 Block Range Granule로 나누어 Scan하더라도 같은 CUSTOMER_ID의 Row가 여러 Producer에 흩어져 있을 수 있습니다. 병렬 Hash Join에서 같은 Join Key를 가진 양쪽 Row가 만나려면, 해당 Key의 Row가 같은 Consumer에 도착하도록 재분배해야 합니다.
Producer 1: customer_id 10, 20, 30
Producer 2: customer_id 10, 40, 50
Producer 3: customer_id 20, 60, 70
↓ HASH(customer_id)
Consumer A: customer_id 10, 10, 40, 70
Consumer B: customer_id 20, 20, 50
Consumer C: customer_id 30, 60
재분배에는 다음 비용이 따릅니다.
- Row 직렬화와 PX Message 생성
- Producer·Consumer 사이 Table Queue 통신
- 같은 Instance 내 Message Buffer 또는 RAC Interconnect 사용
- Consumer Queue 대기와 Backpressure
- Row 수와 Row 폭에 비례하는 Bytes 전송
- Consumer의 Hash·Sort Workarea와 TEMP Spill
따라서 병렬 Scan으로 줄인 시간보다 재분배·동기화 비용이 더 큰지 확인해야 합니다.
2. Join Method와 Distribution Method는 다른 결정이다
다음 두 질문은 별도로 판단합니다.
Join Method
→ 두 Row Source를 어떤 Algorithm으로 연결할 것인가?
→ Nested Loops·Hash Join·Sort Merge Join
PX Distribution Method
→ Producer가 만든 Row를 어느 Consumer에 보낼 것인가?
→ HASH·BROADCAST·RANGE·PARTITION·NONE 등
예를 들어 HASH JOIN을 사용해도 분배 방식은 다음처럼 달라질 수 있습니다.
HASH-HASH
→ 양쪽 Row Source를 Join Key로 Hash 분배
BROADCAST-NONE
→ 작은 Outer Row Source를 모든 Join Consumer에 복제
→ Inner 쪽은 별도 TQ 재분배 없이 Consumer가 처리
PARTITION-NONE
→ Outer Row를 Inner Table의 Partition 배치에 맞춰 이동
NONE-NONE
→ 이미 Join Key로 Equipartition된 대응 Partition Pair끼리 Join
USE_HASH는 Join Algorithm을 시험하고, PQ_DISTRIBUTE는 Producer와 Consumer 사이 Row 배치를 시험합니다. 한 Hint가 다른 결정을 자동으로 확정하지 않습니다.
3. Table Queue와 실행계획에서 분배 읽기
Table Queue는 Producer DFO와 Consumer DFO, 또는 PX Server Set과 QC 사이의 논리적 Row 전달 통로입니다.
Producer Operation
PX SEND <distribution> :TQxxxxx
↓
PX RECEIVE
Consumer Operation
실행계획에서는 다음 항목을 함께 읽습니다.
| 항목 | 의미 |
|---|---|
TQ | 연결된 Table Queue 식별자 |
IN-OUT=P->P | Parallel Producer에서 Parallel Consumer로 전달 |
IN-OUT=P->S | PX Server에서 Serial QC로 전달 |
IN-OUT=S->P | Serial Row Source에서 Parallel Consumer로 전달 |
PQ Distrib | HASH·BROADCAST·RANGE·PART(KEY)·QC(RAND) 등 분배 방식 |
같은 :TQ10000을 가진 PX SEND와 PX RECEIVE를 연결해 어느 Row Source가 어떤 방식으로 이동했는지 읽습니다. PX SEND가 보인다는 사실만으로 비효율이라고 단정하지 않습니다. 해당 전송이 다음 병렬 Operation에 필요한지, Row·Bytes와 Skew가 감당 가능한지를 확인해야 합니다.
4. HASH 분배
HASH 분배는 하나 이상의 Column에 Hash 함수를 적용해 각 Row가 도착할 Consumer를 결정합니다. 다음 식은 개념을 설명하기 위한 단순화이며 Oracle의 내부 Hash 구현을 그대로 뜻하지 않습니다.
consumer = hash(distribution_key) → consumer bucket
같은 Distribution Key는 같은 Consumer로 전달되므로 다음 작업에 적합합니다.
- 병렬 Equi Join
- 병렬 Hash Group By
- 같은 Group Key의 Row를 한 곳에 모아야 하는 Aggregate
- 크기가 비슷한 두 대형 Row Source의 Hash 또는 Sort Merge Join
대표 Plan 형태는 다음과 같습니다.
PX RECEIVE
PX SEND HASH :TQ10000
TABLE ACCESS FULL ORDERS
장점
- Key가 고르면 Consumer별 Row와 Bytes를 비교적 균등하게 분배할 수 있습니다.
- 같은 Key의 Row가 한 Consumer에 모이므로 Join·Group By를 병렬 수행할 수 있습니다.
- 양쪽 대형 입력을 모두 이동시키더라도 Broadcast보다 총 복제량을 줄일 수 있습니다.
위험
- 특정 인기 Key가 전체 Row의 대부분이면 한 Consumer에 집중됩니다.
- NULL·미분류·기본값이 과도하면 하나의 Hash Bucket이 병목이 될 수 있습니다.
- Distinct Value 수가 DOP보다 매우 작으면 일부 Consumer는 일을 받지 못할 수 있습니다.
- Row 수가 고르더라도 일부 Row가 넓으면 Bytes·CPU·TEMP가 편중될 수 있습니다.
고른 분포
Consumer 1: 25만 행 / 2.0GB
Consumer 2: 24만 행 / 1.9GB
Consumer 3: 26만 행 / 2.1GB
Consumer 4: 25만 행 / 2.0GB
편중 분포
Consumer 1: 92만 행 / 7.4GB
Consumer 2: 3만 행 / 0.2GB
Consumer 3: 3만 행 / 0.2GB
Consumer 4: 2만 행 / 0.2GB
전체 경과시간은 가장 늦게 끝나는 Consumer에 좌우됩니다. DOP를 높여도 같은 인기 Key는 한 Consumer로 가므로 단일 Hot Key 문제를 자동으로 해결하지 못합니다.
5. BROADCAST 분배
BROADCAST는 분배 대상 Row Source의 각 Row를 모든 Join Consumer에 복제합니다.
작은 입력 1,000행, Consumer 4개
→ Consumer 1에 1,000행
→ Consumer 2에 1,000행
→ Consumer 3에 1,000행
→ Consumer 4에 1,000행
대표 Plan 형태는 다음과 같습니다.
PX RECEIVE
PX SEND BROADCAST :TQ10000
TABLE ACCESS FULL SMALL_DIMENSION
BROADCAST는 Filter 후 작은 Dimension Row Source를 모든 Consumer에 보내고, 큰 Fact Row Source의 TQ 재분배를 피할 때 유리할 수 있습니다.
개념적 전송량
≈ Broadcast 대상의 실제 Bytes × Consumer 수
이 식은 Protocol Overhead를 제외한 단순화입니다. Optimizer가 1,000행으로 예상했지만 실제로 수천만 행이 반환되거나 DOP가 매우 높으면 Network·PGA·Queue 비용이 급증합니다.
| 적합한 조건 | 위험한 조건 |
|---|---|
| Filter 후 실제 입력이 충분히 작음 | Cardinality 과소 추정 |
| Row 폭이 작고 Consumer 수가 통제됨 | LOB·긴 문자열 등 Row 폭이 큼 |
| 큰 입력의 이동을 피할 수 있음 | DOP가 매우 큼 |
| 작은 Build Row Source를 각 Consumer가 재사용 | 작은 입력 가정이 Runtime에 깨짐 |
NONE은 해당 쪽이 별도의 TQ 분배를 하지 않는다는 의미로 이해해야 합니다. “한 PX Server만 처리한다” 또는 “물리적으로 원래 Process에 고정된다”는 뜻은 아닙니다. Access Granule과 Consumer Set의 작업 배치는 별도로 존재할 수 있습니다.
6. RANGE 분배와 RANGER
RANGE 분배는 Sort Key의 값 범위를 Consumer별로 배정합니다.
Consumer 1: A ~ G
Consumer 2: H ~ M
Consumer 3: N ~ S
Consumer 4: T ~ Z
주로 병렬 Sort에서 사용되며, 같은 범위의 값을 같은 Consumer로 보내 각 Consumer가 자신의 범위를 정렬하도록 합니다.
PX SEND RANGE
→ Sample 또는 Boundary 정보로 범위 결정
→ Consumer별 범위에 Row 전송
→ Consumer별 Sort
→ 범위 순서에 따라 결과 결합
V$PQ_TQSTAT.SERVER_TYPE에는 Producer·Consumer 외에 Range Boundary 계산과 관련된 RANGER가 나타날 수 있습니다.
RANGE 분배의 핵심 위험은 Boundary Skew입니다.
정렬 Key의 70%가 한 경계 범위에 집중
→ 해당 Range Consumer만 오래 Sort
→ TEMP Spill과 경과시간 증가
Row 수뿐 아니라 Bytes, Sort Workarea, TEMP, Key 분포와 Boundary 품질을 함께 확인합니다.
7. PARTITION(KEY) 분배와 Parallel Load
PARTITION 기반 분배는 Row의 Partition Key를 계산하여 대상 Partition을 담당하는 Consumer로 보냅니다.
Row의 Partition Key 계산
→ 대상 Partition 결정
→ 그 Partition을 담당하는 Consumer로 전송
대표 활용은 다음과 같습니다.
- Partial Partition-Wise Join
- Parallel Insert·Update·Delete의 Target Partition 배치
- Partitioned Table의 Parallel Load
Join Plan의 PQ Distrib에는 PART (KEY)가 나타날 수 있습니다.
PX SEND PARTITION (KEY)
→ 상대 Row Source 또는 대상 Table의 Partition 배치에 맞춰 Row 이동
효과를 판단할 때는 다음을 확인합니다.
- Join·DML Key와 Partition Key의 일치 여부
- Partition 경계 또는 Hash 배치의 호환성
- Partition별 Row·Bytes 편중
- 대상 Partition 수와 DOP
- 하나의 Partition이 지나치게 큰지 여부
PARTITION 분배는 Join Algorithm이 아니라 Row를 담당 Partition 위치에 맞추는 Data Placement 방식입니다.
8. HYBRID HASH: Runtime에 BROADCAST와 HASH 선택
HYBRID HASH는 Join의 왼쪽 Row Source 크기를 실행 중 관찰하여 분배 방식을 선택하는 Adaptive Distribution입니다.
왼쪽 결과가 Threshold 이하
→ 왼쪽 BROADCAST
→ 오른쪽은 별도 Hash 재분배 없이 Consumer가 처리
왼쪽 결과가 Threshold 초과
→ 양쪽 HASH 분배
실행계획에는 다음과 같은 단서가 나타날 수 있습니다.
PX SEND HYBRID HASH
STATISTICS COLLECTOR
왼쪽 Row Source
Parse 시점의 Cardinality만으로 작은 입력 여부를 확정하기 어려울 때 Runtime Row 수를 이용합니다. 그러나 HYBRID HASH가 통계정보 문제를 없애 주는 것은 아닙니다. 부정확한 통계는 Join Order, Join Method, Access Path, Workarea 크기 등 다른 결정에도 영향을 줍니다.
실제 선택 결과는 Plan 문구 하나만으로 단정하지 않고 SQL Monitor, V$PQ_TQSTAT의 Row·Bytes, Runtime Row Source 통계로 확인합니다.
9. Join용 PQ_DISTRIBUTE의 여섯 가지 유효 조합
Join에 사용하는 PQ_DISTRIBUTE(inner_alias outer_distribution inner_distribution)는 지정한 Alias를 Inner Row Source로 해석하며, 두 분배 인자는 Outer와 Inner의 배치를 뜻합니다.
| 조합 | 의미와 주요 조건 |
|---|---|
HASH HASH | 양쪽을 Join Key로 Hash 분배. 크기가 비슷한 대형 입력의 Equi Join에 적합 |
BROADCAST NONE | Outer를 모든 Consumer에 복제. Inner는 별도 TQ 재분배 없이 처리 |
NONE BROADCAST | Inner를 모든 Consumer에 복제. Outer는 별도 TQ 재분배 없이 처리 |
PARTITION NONE | Outer를 Inner Table의 Partition 배치에 맞춤. Inner가 Join Key로 Partition되고 Equi Join이어야 함 |
NONE PARTITION | Inner를 Outer Table의 Partition 배치에 맞춤. Outer가 Join Key로 Partition되고 Equi Join이어야 함 |
NONE NONE | 대응 Partition Pair끼리 Join. 양쪽이 Join Key로 Equipartition되어야 함 |
유효하지 않은 조합, 잘못된 Alias, 실제 Join Order와 맞지 않는 지정, Partition 조건 미충족 시 Hint가 적용되지 않을 수 있습니다. Hint Report 또는 Outline과 실제 PQ Distrib을 확인합니다.
10. Parallel Load용 PQ_DISTRIBUTE는 문법과 목적이 다르다
Parallel INSERT ... SELECT 또는 CREATE TABLE ... AS SELECT에서 PQ_DISTRIBUTE(target_alias method)는 Join용 두 인자 문법이 아니라 Load Server로 Row를 배치하는 단일 방식을 지정합니다.
| Load 분배 | 의미 |
|---|---|
NONE | Query와 Load를 같은 PX Server에서 결합해 TQ 분배를 피함. Partition별 Memory와 Skew에 주의 |
PARTITION | Target Partition 정보로 Load Server에 Row 배치. Partition 수와 분포가 충분히 고른 경우 적합 |
RANDOM | Producer Row를 Consumer에 Round-Robin으로 분배. 입력 Skew 완화 목적 |
RANDOM_LOCAL | 특정 Partition 담당 Server 집합 안에서 분산. Skew와 Memory 제약을 함께 고려 |
Join 분배의 HASH HASH와 Load 분배의 RANDOM을 같은 문법으로 혼동하지 않습니다.
11. Bloom Filter의 원리와 적용 범위
Bloom Filter는 Build Key 집합을 작은 Bit Array로 요약하여 Probe 값이 그 집합에 포함될 가능성을 검사합니다.
Build Input의 Join Key
→ 여러 Hash 함수 적용
→ Bloom Filter Bit 설정
→ Probe Row에 Membership Test
→ 확실히 없음: 조기 제거
→ 있을 수 있음: 실제 Join Key 비교로 전달
판단 특성
| 결과 | 의미 |
|---|---|
| 하나 이상의 필요한 Bit가 0 | 해당 Key는 확실히 집합에 없음 → 제거 가능 |
| 필요한 Bit가 모두 1 | 집합에 있을 수 있음 → 실제 Join에서 다시 비교 |
| False Positive | 실제 Match가 없지만 Filter를 통과할 수 있음 |
| False Negative | 존재하는 Key를 없다고 판단하는 경우로, 정상 Bloom Filter에서는 발생하지 않음 |
Bloom Filter는 최종 Join 판정을 대신하지 않습니다. 통과한 Row는 “일치 가능성 있음”일 뿐이며 실제 Join Operation에서 정확한 Key 비교가 필요합니다.
Oracle은 Bloom Filter를 다음 목적으로 사용할 수 있습니다.
- Parallel Query에서 Child Process로 전송되는 Row 감소
- Join 기반 Partition Pruning
- Server Result Cache Membership 검사
- Exadata Cell에서 Fact·Dimension Join Filtering
Bloom Filter는 병렬 실행에서 특히 중요하지만 직렬 처리에서도 나타날 수 있습니다. PX_JOIN_FILTER는 일반 Bloom Filter 전체를 뜻하는 이름이 아니라 Optimizer에 Parallel Join Bitmap Filtering을 사용하도록 지시하는 Hint입니다.
12. Bloom Filter 실행계획과 Runtime 통계
실행계획에서는 다음 단서를 확인합니다.
JOIN FILTER CREATE :BF0000
...
JOIN FILTER USE :BF0000
또는 Predicate Information에 다음과 같은 내부 표현이 보일 수 있습니다.
SYS_OP_BLOOM_FILTER(:BF0000, "O"."CUSTOMER_ID")
단, Version과 Plan 형태에 따라 표시 방식은 달라질 수 있으므로 Operation 하나만으로 효과를 단정하지 않습니다.
V$SQL_JOIN_FILTER
활성 Bloom Filter의 PROBED와 FILTERED를 확인하여 얼마나 많은 Row가 검사되고 제거되었는지 봅니다.
SELECT sql_id,
filter_id,
probed,
filtered
FROM v$sql_join_filter
WHERE sql_id = :sql_id;
통과 Row 개념값 = PROBED - FILTERED
통과 Row 전체가 실제 Join 성공 Row라는 뜻은 아닙니다. False Positive가 포함될 수 있어 최종 Join A-Rows와 함께 비교해야 합니다.
V$PQ_TQSTAT
Bloom Filter 적용 전후의 TQ Row·Bytes를 비교해 Process 간 전송량 감소 여부를 확인합니다. JOIN FILTER CREATE가 보였다는 사실보다 Scan 출력, TQ 전송량, Join 입력, 경과시간이 실제로 줄었는지가 중요합니다.
13. Data Skew의 유형과 발생 위치
병렬 Skew는 PX Server별 작업량이 불균등한 상태입니다.
13.1 Producer Skew
초기 Scan 또는 Filter 단계부터 일부 Producer가 훨씬 많은 Row를 생성합니다.
- Partition 크기 편중
- Granule 배정 불균형
- Predicate가 일부 Partition에서만 많은 Row를 반환
- RAC Instance별 I/O 차이
13.2 Distribution Skew 또는 Join Key Skew
Producer는 고르게 Row를 만들었지만 HASH·RANGE·PARTITION 분배 후 일부 Consumer에 집중됩니다.
- 인기 Join Key
- NULL·기본값 편중
- 낮은 NDV
- Range Boundary 편중
- Partition별 크기 편중
13.3 Row Width Skew
Row 수는 비슷하지만 일부 PX가 LOB·긴 문자열·넓은 Row를 많이 처리하여 Bytes·CPU·Memory가 커집니다.
13.4 Workarea Skew
특정 Consumer의 Hash Table 또는 Sort Run만 커져 TEMP Spill과 긴 A-Time이 발생합니다.
Skew는 Row 수만으로 판단하지 않습니다.
- PX별
NUM_ROWS - PX별
BYTES OPEN_TIME·WAITS·TIMEOUTS- Operation별
A-Time·CPU - Workarea Memory와 TEMP
- RAC Cross-Instance 전송
14. V$PQ_TQSTAT으로 분배 편차 검증
V$PQ_TQSTAT은 Parallel Query가 완료된 뒤 같은 Session에만 남는 TQ 통계입니다. Parallel DML에서는 Commit 또는 Rollback 이후 확인할 수 있습니다.
SELECT dfo_number,
tq_id,
server_type,
instance,
process,
num_rows,
bytes,
open_time,
waits,
timeouts
FROM v$pq_tqstat
ORDER BY dfo_number,
tq_id,
server_type,
instance,
process;
같은 TQ와 같은 SERVER_TYPE 안에서 최대·평균 Row와 Bytes를 비교합니다.
SELECT dfo_number,
tq_id,
server_type,
MIN(num_rows) AS min_rows,
MAX(num_rows) AS max_rows,
ROUND(AVG(num_rows), 1) AS avg_rows,
ROUND(MAX(num_rows) / NULLIF(AVG(num_rows), 0), 2)
AS row_max_to_avg,
MIN(bytes) AS min_bytes,
MAX(bytes) AS max_bytes,
ROUND(AVG(bytes), 1) AS avg_bytes,
ROUND(MAX(bytes) / NULLIF(AVG(bytes), 0), 2)
AS byte_max_to_avg
FROM v$pq_tqstat
GROUP BY dfo_number, tq_id, server_type
ORDER BY dfo_number, tq_id, server_type;
MAX ÷ AVG가 1에 가까울수록 균등한 경향을 보이지만, 이를 고정 임계값으로 사용하지 않습니다.
4개 Consumer Row = 800, 100, 50, 50
평균 = 250
MAX ÷ AVG = 800 ÷ 250 = 3.2
작은 절대 Row 수에서 비율만 높을 수 있고, 모든 PX가 동일하게 느린 경우 비율은 낮아도 전체 비용이 클 수 있습니다. Row·Bytes·시간과 업무 기준을 함께 봅니다.
발생 위치 구분
Producer Row부터 편중
→ Source Scan·Partition·Predicate·Granule 문제 가능성
Producer는 고른데 Consumer만 편중
→ HASH Key·Range Boundary·Partition Distribution 문제 가능성
Row는 고른데 Bytes만 편중
→ Row Width Skew 가능성
15. Hint의 역할과 주의점
PQ_DISTRIBUTE
Join 또는 Parallel Load의 분배 방식을 제한적으로 시험합니다. Alias, Join Order, Equi Join, Partition 조건과 문법이 맞아야 하며 실제 적용 여부는 Hint Report와 Plan에서 검증합니다.
PQ_SKEW
Parallel Hash Join의 Join Key 값 분포가 심하게 편중되었음을 Optimizer에 알리는 Hint입니다. tablespec에는 Hash Join의 Probe Table을 지정합니다. 내부 처리 효과를 추측하지 말고 실제 Consumer Row·Bytes·경과시간으로 검증합니다.
PX_JOIN_FILTER
Parallel Join Bitmap Filtering을 사용하도록 지시합니다. Filter 생성 여부만 보지 말고 다음을 비교합니다.
V$SQL_JOIN_FILTER.PROBED·FILTERED- Probe Scan과 Join Input의
A-Rows - TQ
NUM_ROWS·BYTES - Scan·Join 경과시간
- 새로운 CPU·Memory 부작용
Hint는 통계·Data Model·Partition 설계·Join Order 문제를 가리는 영구 처방이 아니라 원인 가설을 검증하는 실험 수단입니다.
16. 혼동하기 쉬운 판단
| 혼동하기 쉬운 판단 | 정확한 기준 |
|---|---|
HASH JOIN이면 반드시 PX SEND HASH | Join Algorithm과 PX Distribution은 별도 결정 |
BROADCAST는 작은 입력을 한 PX에 보냄 | 작은 입력의 각 Row를 모든 Join Consumer에 복제 |
NONE이면 해당 Row Source를 한 Process가 처리 | 별도 TQ 재분배가 없다는 뜻이며 Access·Granule 배치는 별도 |
RANGE는 값 범위를 항상 균등하게 나눔 | Boundary와 데이터 분포에 따라 Range Skew 가능 |
PART(KEY)는 Join Method | Partition 배치에 맞추는 Data Placement 방식 |
| HYBRID HASH면 통계가 불필요 | Runtime 분배 선택만 보완하며 다른 Optimizer 결정에는 통계가 필요 |
| Bloom Filter 통과는 Join 성공 | 일치 가능성만 의미하며 False Positive 가능 |
| Bloom Filter는 병렬 SQL에만 존재 | 직렬 처리에서도 사용 가능 |
PX_JOIN_FILTER는 모든 Bloom Filter를 강제 | Parallel Join Bitmap Filtering을 지시하는 Hint |
| PX별 Row 수만 같으면 균등 | Bytes·CPU·TEMP·Wait·A-Time도 확인 |
| DOP를 높이면 Hot Key가 분산 | 같은 Hash Key는 같은 Consumer로 가므로 해결되지 않을 수 있음 |
17. 실전 진단 절차
1. 실제 Cursor의 Join Order와 Join Method 확인
2. PX SEND·PX RECEIVE를 TQ 기준으로 연결
3. IN-OUT과 PQ Distrib으로 Row 이동 방향 확인
4. E-Rows와 A-Rows로 분배 대상 크기 오차 확인
5. BROADCAST 대상의 실제 Row·Bytes와 Consumer 수 확인
6. V$PQ_TQSTAT에서 Producer·Consumer별 NUM_ROWS·BYTES 비교
7. Producer Skew와 Distribution Skew 발생 위치 구분
8. HASH Key의 인기값·NULL·기본값·NDV 확인
9. RANGE Boundary 또는 Partition 크기 편중 확인
10. JOIN FILTER CREATE·Predicate와 V$SQL_JOIN_FILTER 확인
11. Bloom Filter 전후 Scan·TQ·Join A-Rows와 경과시간 비교
12. Hint 실험 후 전체 Resource와 시스템 Throughput까지 비교
병렬 분배 튜닝의 핵심은 특정 PX SEND 이름을 암기하는 것이 아닙니다. 어떤 Row Source를 어느 Consumer로 얼마나 이동시키고, 그 결과 Row·Bytes·시간이 얼마나 균등해졌는지 설명할 수 있어야 합니다.
핵심 정리
HASH
→ 같은 Distribution Key를 같은 Consumer로 전송
BROADCAST
→ 분배 대상 Row를 모든 Join Consumer에 복제
RANGE
→ Sort Key 범위별 Consumer 배정
PARTITION(KEY)
→ 상대 또는 Target Partition 배치에 맞춰 Row 이동
HYBRID HASH
→ Runtime 왼쪽 Row 수에 따라 BROADCAST·HASH 선택
Bloom Filter
→ 확실히 불일치하는 Probe Row를 조기 제거
→ False Positive 가능, False Negative 불가
검증
→ 실제 Cursor Plan + V$PQ_TQSTAT + V$SQL_JOIN_FILTER + SQL Monitor
개념 확인 문제
문제를 누르면 바로 아래에서 정답과 해설을 확인할 수 있습니다.
01병렬 실행에서 Producer가 만든 Row를 다른 Consumer Set으로 다시 배치하는 과정을 무엇이라고 하는가?
Data Redistribution 또는 PX Data Distribution입니다. Producer PX Server Set이 만든 Row를 다음 Join·Sort·Aggregate·Load를 담당하는 Consumer PX Server Set에 맞게 다시 배치하는 과정입니다.
02HASH JOIN과 PX SEND HASH가 서로 다른 결정인 이유는 무엇인가?
HASH JOIN은 두 Row Source를 연결하는 Join Algorithm이고, PX SEND HASH는 Row를 어느 Consumer로 보낼지 정하는 Distribution Method이기 때문입니다. Hash Join도 Broadcast·Partition·None 등의 다른 분배와 결합할 수 있습니다.
03같은 Distribution Key의 Row를 같은 Consumer로 보내는 방식과 대표 위험은 무엇인가?
HASH 분배이며 대표 위험은 Join Key Skew입니다. 같은 Key는 같은 Consumer에 도착하므로 인기 Key·NULL·기본값이 많으면 한 Consumer에 Row·Bytes·Workarea가 집중될 수 있습니다.
04BROADCAST의 개념적 전송량과 실제 입력이 예상보다 클 때의 위험은 무엇인가?
개념적으로 Broadcast 대상 실제 Bytes × Consumer 수입니다. 실제 Row 수·Row 폭 또는 DOP가 예상보다 크면 Network·PGA·Queue 전송량이 급증하고 작은 입력이라는 전제가 무너집니다.
05RANGE 분배에서 RANGER와 Boundary Skew는 무엇을 의미하는가?
RANGER는 Range Boundary 계산과 관련된 Server Type이며, Boundary Skew는 데이터가 특정 값 범위에 집중되어 해당 Range Consumer만 과도하게 일하는 상태입니다. Row·Bytes·TEMP를 함께 확인합니다.
06Join용 PQDISTRIBUTE의 여섯 가지 유효 조합은 무엇인가?
HASH HASH, BROADCAST NONE, NONE BROADCAST, PARTITION NONE, NONE PARTITION, NONE NONE입니다. Partition 조합은 Join Key Partition과 Equi Join 조건이 필요하고 NONE NONE은 Equipartition이 필요합니다.
07Parallel Load용 PQDISTRIBUTE와 Join용 문법은 어떻게 다른가?
Join용은 Inner Alias 뒤에 Outer·Inner 두 분배 방식을 지정하고, Parallel Load용은 Target Alias 뒤에 NONE·PARTITION·RANDOM·RANDOM_LOCAL 중 하나를 지정합니다. 목적과 유효 Method가 다릅니다.
08HYBRID HASH는 어떤 Runtime 조건에 따라 어떤 두 분배 방식 중 하나를 선택하는가?
왼쪽 Row Source의 Runtime Row 수를 Threshold와 비교합니다. Threshold 이하이면 왼쪽 BROADCAST와 오른쪽 무재분배를 사용하고, 초과하면 양쪽 HASH 분배를 사용합니다.
09Bloom Filter의 False Positive·False Negative 특성과 V$SQLJOINFILTER의 주요 지표는 무엇인가?
False Positive는 가능하지만 False Negative는 발생하지 않습니다. V$SQL_JOIN_FILTER.PROBED는 검사 Row 수, FILTERED는 제거 Row 수이며, PROBED-FILTERED는 통과 Row 개념값이지만 실제 Join 성공 Row 수와 같지는 않습니다.
10V$PQTQSTAT의 통계 수명과 Producer Skew·Distribution Skew를 구분하는 방법은 무엇인가?
Query 완료 후 같은 Session 동안만 유지되며 Parallel DML은 Commit 또는 Rollback 이후 확인합니다. Producer부터 편중이면 Scan·Partition·Predicate 문제를, Producer는 고른데 Consumer만 편중이면 Distribution Key·Range Boundary·Partition 배치를 우선 의심합니다.