728x90
반응형
SMALL

지난 포스팅에 이어서 실제 Hive + Spark 예제로 심화편을 단계적으로 풀어보려고 한다.
이번엔 실무에서 자주 쓰는 대용량 테이블 조인 최적화를 집중적으로 다뤄 보겠다
목표 시나리오
- raw_event 테이블: 수십억 행의 로그 데이터
- user_profile 테이블: 수백만 행의 유저 정보 (작음)
요구사항:
- 최근 1개월 raw_event에서 특정 조건만 필터링 →
- user_profile과 조인 →
- 유저별 활동 집계 →
- 결과 저장.
잘못된 접근 (느린 쿼리 예)
SELECT
p.user_id,
p.age_group,
COUNT(e.event_id) AS event_count
FROM
raw_event e
JOIN
user_profile p
ON
e.user_id = p.user_id
WHERE
e.event_date >= '2025-06-01'
GROUP BY
p.user_id, p.age_group;
문제점!
- raw_event는 수십억 행인데, user_profile을 바로 조인한다.
- Spark는 Shuffle Join 수행 → 대량 데이터 재분배 → 디스크 I/O + 네트워크 비용 ↑
- 파티션 조건이 늦게 걸려서 Full Scan 발생.
성능 좋은 접근 — 단계별 Temp Table 활용
1. 먼저 필터링 + 집계 → Temp Table로 저장
CREATE TABLE temp_event_summary AS
SELECT
user_id,
COUNT(event_id) AS event_count
FROM
raw_event
WHERE
event_date >= '2025-06-01'
GROUP BY
user_id;
여기서 이미 데이터량이 90% 이상 줄어든다!!
2. Temp Table과 작은 테이블 조인
SELECT
p.user_id,
p.age_group,
t.event_count
FROM
temp_event_summary t
JOIN
user_profile p
ON
t.user_id = p.user_id;
장점
- 큰 테이블 → 작은 Temp Table로 변환 → 조인 비용 대폭 감소.
- user_profile은 작은 테이블이라 Spark가 Broadcast Join 사용 가능 → Shuffle 방지.
Spark로 Broadcast Join 강제
Spark는 작은 테이블이면 자동으로 Broadcast Join을 시도한다.
그러나 크기를 못 추정하면 못할 수도 있으니, 명시적 힌트가 좋다.
SELECT /*+ BROADCAST(p) */
p.user_id,
p.age_group,
t.event_count
FROM
temp_event_summary t
JOIN
user_profile p
ON
t.user_id = p.user_id;
/*+ BROADCAST(테이블) */ → 작은 테이블을 Executor에 복제해서 Shuffle 없이 Local Join.
저장 포맷 최적화 — 컬럼형 + 압축
CREATE TABLE temp_event_summary
STORED AS PARQUET
AS
SELECT ...
- Hive에서 TEXTFILE 대신 Parquet, ORC 사용 → 필요한 컬럼만 읽음.
- Snappy 같은 경량 압축 적용 → 스캔 I/O 대폭 절감.
실행 계획 확인은 필수
Hive와 Spark SQL 모두 EXPLAIN 으로 플랜 확인해야 한다.
EXPLAIN
SELECT
...
- 어떤 단계에서 Shuffle이 발생하는지
- 어떤 쿼리 블록이 Full Scan인지
- 파티션 Pruning이 정상 동작하는지
플랜 안 보면 결국 ‘느린 이유 모름’ 상태 된다.
실전 꿀팁 요약!!
|
핵심 포인트
|
실전 대응
|
|
대용량 테이블
|
반드시 필터 → 집계 → Join
|
|
작은 테이블
|
Broadcast Join 강제
|
|
Shuffle 최소화
|
파티션 키 맞춰서 Join
|
|
저장 포맷
|
컬럼형 + Snappy
|
|
실행 계획
|
EXPLAIN 필수
|
+ 확장 아이디어
- Dynamic Partition Pruning (DPP): Spark 3.0부터 지원. Join 전에 파티션 자동 줄이기.
- Z-Order Clustering (Databricks): 필터 성능 극대화.
- Materialized View: 정기 집계 결과 사전 생성.
학스의 개발일지
일상과 코딩 그 사이 어딘가에있는 블로그.. 블로거이자 빅데이터개발자 학스 입니다 JAVA, jQuery, PostgreSQL, MySQL, HIVE, Hadoop 더 많은 정보는 깃허브 주소 https://github.com/hacs2772 를 방문해주세요
hacs2772.tistory.com
728x90
반응형
LIST
'TIPS' 카테고리의 다른 글
| 실무에서 자주 쓰이지만 까다로운 SQL 문법 정리 (8) | 2025.07.28 |
|---|---|
| Spark 실전 성능 튜닝 #Executor, #Shuffle, #GC (4) | 2025.07.21 |
| #빅데이터 실무에서 성능 잡아먹는 핵심 원인과 실전 대응 (2) | 2025.07.07 |
| #ConcurrentHashMap 안전한 멀티스레드 Map의 모든 것 (1) | 2025.06.30 |
| Java Memory Model (JMM)과 volatile 키워드 — 동시성 프로그래밍의 핵심 (2) | 2025.06.23 |