조인 전략 선택 — 힌트와 4가지 물리적 조인 방식
Apache Spark 튜닝 옵션 카탈로그 — 공식 설정 문서 종합 (웹 리서치, 2026) — Apache Spark 공식 문서(sql-performance-tuning.html, configuration.html, Spark 4.2.0 기준) Spark 4.2.0 공식 문서 sql-performance-tuning.html — Join Strategy Hints
이 모듈을 다 읽으면
- Spark가 지원하는 4가지 물리적 조인 전략과 각각이 유리한 상황을 구분할 수 있다
- 조인 힌트를 코드에 명시했을 때 Spark의 자동 판단보다 우선하는 원리와 힌트 간 우선순위를 설명할 수 있다
- spark-learn-32에서 검증한 BroadcastHashJoin 확인 방법을 다른 조인 전략에도 응용할 수 있다
spark-learn-32가 다룬 조인 결과 검증(cache/left_anti/BroadcastHashJoin 확인)을 전제로, Spark의 4가지 물리적 조인 전략과 이를 명시적으로 지정하는 힌트 문법·우선순위를 정리한다.
Spark가 고를 수 있는 4가지 물리적 조인 전략
논리적으로 같은 join이라도 Spark는 실행 시점에 네 가지 물리적 전략 중 하나를 고른다. (1) Broadcast Hash Join — 한쪽 테이블이 충분히 작으면(spark.sql.autoBroadcastJoinThreshold, 기본 10MB 미만) 그 테이블 전체를 모든 executor에 복사해 셔플 자체를 없앤다. 가장 빠르지만 작은 쪽이 실제로 메모리에 들어갈 만큼 작아야 한다. (2) Sort-Merge Join — 양쪽을 조인 키로 정렬한 뒤 병합하는 기본 전략. 양쪽 다 크고 브로드캐스트가 불가능할 때 기본으로 선택된다(spark.sql.join.preferSortMergeJoin, 기본 true). (3) Shuffled Hash Join — 정렬 없이 한쪽으로 해시 맵을 만들어 조인한다. 정렬 비용을 아낄 수 있지만 해시 맵이 파티션당 메모리에 다 들어가야 한다(AQE의 maxShuffledHashJoinLocalMapThreshold로 유도 가능, 모듈 41 참고). (4) Shuffle-and-Replicate Nested Loop Join — 동등 조인 조건(equi-join, key = key)이 아닌 조인(예: 범위 조인 a.x BETWEEN b.lo AND b.hi)에서 다른 방법이 없을 때 쓰는 최후 수단으로, 양쪽을 전부 비교하므로 가장 느리다.
핵심 포인트
- Broadcast Hash Join: 한쪽이 작을 때(기본 10MB 미만) 셔플 자체를 없애는 가장 빠른 전략
- Sort-Merge Join: 양쪽이 크고 브로드캐스트 불가할 때의 기본 전략(양쪽 정렬 후 병합)
- Shuffled Hash Join: 정렬을 생략하고 해시 맵으로 조인 — 파티션당 해시맵이 메모리에 들어가야 유리
- Shuffle-and-Replicate Nested Loop Join: equi-join이 아닌 조인의 최후 수단, 가장 느림
조인 힌트로 자동 판단을 오버라이드하기
Spark의 자동 판단(테이블 크기 추정 기반)이 항상 맞는 것은 아니다 — 특히 복잡한 변환을 거친 뒤라 통계가 부정확하거나, 외부 소스 통계가 없을 때 오판할 수 있다. 이럴 때 SQL 힌트나 DataFrame API의 .hint()로 원하는 전략을 직접 지정할 수 있다.
SQL: `SELECT /*+ BROADCAST(r) */ * FROM src s JOIN records r ON s.key = r.key` / PySpark: `spark.table("src").join(spark.table("records").hint("broadcast"), "key")`. 힌트 종류는 BROADCAST, MERGE(sort-merge 강제), SHUFFLE_HASH, SHUFFLE_REPLICATE_NL 네 가지이며, 여러 힌트가 충돌하면 이 순서로 우선순위가 적용된다: BROADCAST > MERGE > SHUFFLE_HASH > SHUFFLE_REPLICATE_NL. 즉 BROADCAST 힌트를 준 조인은 다른 힌트나 자동 판단보다 항상 우선해서 적용된다.
힌트를 준 결과가 실제로 의도한 전략으로 실행됐는지는 spark-learn-32에서 다룬 방식대로 .explain()의 물리 실행 계획에서 BroadcastHashJoin/SortMergeJoin/ShuffledHashJoin 문자열을 직접 확인하는 것이 유일하게 확실한 검증 방법이다 — 힌트를 줬다고 항상 그대로 적용되는 것은 아니다(예: BROADCAST 힌트를 줬는데 그 테이블이 실제로는 너무 커서 메모리에 안 들어가면 OOM 위험이 있어 Spark가 무시하거나 다른 방식을 택할 수 있다).
핵심 포인트
- 조인 힌트 4종: BROADCAST, MERGE, SHUFFLE_HASH, SHUFFLE_REPLICATE_NL — SQL 주석(/*+ ... */) 또는 DataFrame.hint()로 지정
- 힌트 충돌 시 우선순위는 BROADCAST > MERGE > SHUFFLE_HASH > SHUFFLE_REPLICATE_NL
- 힌트를 줬다고 항상 그대로 적용되지는 않는다 — .explain()으로 실제 물리 실행 계획을 확인하는 것이 유일하게 확실한 검증