Spark SQL 진단은(는) 무엇을 하나요?
사용 시기
사용자가 다음 조합 중 하나를 제공할 때 사용하세요:
- Spark UI / History Server / YARN proxy 주소;
- Spark SQL과 그
EXPLAIN FORMATTED; - Kyuubi / Spark Driver 실행 로그;
/api/v1/...에서 내보낸 JSON 또는 event log.
목표는 "몇 가지 지표를 보는 것"이 아니라, 다음 질문에 답하는 것입니다:
- 이 쿼리가 느린 계층은 무엇인가: 스캔, 셔플, 조인, 집계, spill, GC, 스케줄링, 콜드 스타트;
- 데이터 기울어짐이 있는가, 있다면 어떤 stage / task / SQL 조각에서 발생하는가;
- 무엇이 데이터 문제이고, 무엇이 리소스 또는 설정 문제인가;
- 다음 단계는 SQL 수정, 설정 변경, 또는 데이터 보충 중 무엇인가.
입력 우선순위
| 입력 | 할 수 있는 작업 |
|---|---|
| UI 주소 + Execution ID/제출 시간 + SQL | 가장 완전, task 수준 진단 |
| 실행 로그 (app ID 및 UI 주소 포함) + SQL | 로그를 먼저 분석한 후 UI 접근; UI를 사용할 수 없으면 stage 수준으로 다운그레이드 |
| EXPLAIN FORMATTED | 계획 구조와 SQL 조각 매핑만 가능 |
| event log / History Server | UI 만료 후의 보완책 |
로그에는 일반적으로 다음이 이미 포함되어 있습니다:
application ID: application_xxx
application web UI: http://host:8088/proxy/application_xxx
따라서 사용자가 UI 주소를 별도로 붙여넣을 필요는 없지만, 실제로 해당 주소에 접근 가능한지 반드시 확인해야 합니다.
작업 흐름
1. 입력 수집 및 파싱
- 로그에서 app ID, UI 주소, operation ID, stage/job 타임라인, Final Plan 추출;
- SQL 원문에서 테이블명, 조인 조건, group by / distinct / window / order by 추출;
EXPLAIN FORMATTED에서 연산자, 입출력 컬럼, 조인 조건, 집계 키 추출.
2. 실제 실행 위치 확인
- 우선 Execution ID 사용;
- 그렇지 않으면 SQL 텍스트 + 제출 시간을 기준으로
/sql목록에서 매칭; /sql은 기본적으로 offset=0에서 시작하는 소량의 레코드만 반환하므로, 반드시 페이지네이션 또는 ID로 탐색해야 함;- 여러 후보가 있는 경우, 시간이 가장 최근이고 설명이 일치하는 것을 선택; 그래도 유일하지 않으면 사용자에게 문의.
3. 실행 데이터 가져오기
스크립트 실행 (권장). 다음 scripts/는 이 스킬 디렉터리를 기준으로 합니다. 다른 디렉터리에서 실행하는 경우 먼저 스킬 디렉터리로 cd하거나 절대 경로를 사용하세요.
python scripts/spark_diagnose.py \
--url "http://host:8088/proxy/application_xxx" \
--exec-id 94 \
--sql-file query.sql \
--explain explain.txt \
--log run.log \
--out report.md \
--json report.json
Execution ID를 모르는 경우:
python scripts/spark_diagnose.py \
--url "http://host:18080/history/application_xxx/" \
--sql-file query.sql \
--exec-time "2026-11-02T08:06:50Z" \
--out report.md
인증 파라미터:
--cookie "name=value; name2=value2"
--header "X-Token: ..."
--user "user:password"
--kerberos # curl --negotiate 사용
--insecure # TLS 검증 생략, 내부망 자체 서명 인증서 전용
읽기 전용 원칙: 스크립트는 GET만 호출하고, SQL을 실행하지 않으며, 클러스터에 쓰지 않습니다.
4. 지표 해석
스크립트는 구조화된 JSON과 마크다운을 출력합니다. 핵심 사항:
- Stage 타임라인: wall clock vs
executorRunTimevs task 시작 지연; - task 분포: duration, records, shuffle bytes의 max/median/p95;
- 진성 기울어짐: 한 task의 records와 duration이 모두 중앙값보다 현저히 높음;
- 가짜 긴 꼬리: task record 수는 정상이지만
executorDeserializeTime이 매우 높음, 일반적으로 콜드 executor; - spill:
memoryBytesSpilled/diskBytesSpilled, 그리고 계획 노드의spill size; - 계획 노드: Scan, Exchange, Join, Aggregate의 output rows / shuffle bytes / duration;
- 설정: AQE, skewJoin 임계값, 셔플 파티션 수, 브로드캐스트 임계값, 동적 할당.
5. 최종 보고서 작성
스크립트는 증거와 후보 결론을 제공합니다. 최종 답변은 반드시 SQL 의미를 결합하여 다음을 추가해야 합니다:
- 연산자 → SQL 조각 매핑;
- 핫 키의 비즈니스 의미 (SQL/테이블 생성 로직에서 추론 가능한 경우);
- 권장 사항의 우선순위와 예상 효과;
- "외부 검증 필요" 부분을 명확히 표기.
보고서 구조:
- 결론 우선 순서 (영향 순);
- 실행 개요 및 타임라인;
- 기울어짐/긴 꼬리 증거 테이블;
- SQL 계획 매핑;
- 설정 및 리스크;
- 권장 사항;
- 증거 출처 및 한계;
- 여전히 외부 검증이 필요한 문제.
핵심 판단 규칙
다음 규칙을 반드시 준수하여 가장 흔한 오판을 피해야 합니다:
-
기울어짐은 records와 duration을 보고, shuffle bytes만 보지 마십시오. 압축 가능성이 높은 핫 키 (예: 많은
item_id=1)는 몇 MB에 불과할 수 있지만, records 수는 60%를 차지합니다. -
진성 기울어짐과 콜드 스타트를 구분하십시오. 느린 task의 records 수는 정상이지만
executorDeserializeTime / duration이 높다면, 이는 데이터 기울어짐이 아니라 콜드 executor입니다. -
부분 집계가 GROUP BY 기울어짐을 가릴 수 있습니다. 계획에
partial_count/partial_sum이 있는 경우, 핫 키는 셔플 전에 소량의 행으로 압축됩니다. 집계 작성 방식 자체가 기울어짐을 회피했는지 확인해야 합니다. -
count(DISTINCT)는 2단계 중복 제거입니다. 첫 번째 셔플의 키는 일반적으로 distinct 필드 (예:(item_id, buyer_id))를 포함하므로, 핫 키가 분산됩니다. 일반 GROUP BY로 판단하지 마십시오. -
AQE skew join은 크기 기반입니다. 판단 기준은 압축된 파티션 크기와
skewedPartitionFactor/skewedPartitionThresholdInBytes입니다. 압축 가능한 핫 키는 임계값보다 낮아 분할되지 않을 수 있습니다. -
셔플 파티션 수를 늘려도 단일 hot key는 희석되지 않습니다. 단일 키는 항상 하나의 파티션으로 이동합니다. 파티션이 많을수록 다른 파티션은 더 작아지고, max/median은 오히려 커집니다.
-
Stage wall clock이 task 실행 시간보다 훨씬 크면, 먼저 스케줄링을 확인하십시오.
launchTime - submissionTime, 동적 할당minExecutors, YARN 큐를 확인하세요. -
조인의 출력 행 수가 입력 행 수보다 현저히 클 때만 팽창을 의심하십시오. 출력 행 수가 사실 테이블의 행 수와 같다면, 문제는 일반적으로 분포이지 중복 키 때문이 아닙니다.
경계
- 실제 데이터 내용은 볼 수 없습니다. 핫 키의 구체적인 값은 사용자가 데이터를 확인해야 합니다.
- YARN 큐 대기, 컨테이너 할당 지연의 구체적인 원인은 RM/Kyuubi 로그가 필요합니다.
- UDF/사용자 정의 코드 문제는 코드와 executor 로그가 필요합니다.
- UI/event log가 없는 경우, 일반 driver 로그는 stage 수준 진단만 가능합니다.
- SQL을 실행하지 않고, 데이터를 수정하지 않으며, cookie/token을 출력하지 않습니다.
참고
references/endpoints.md: REST 엔드포인트 및 페이지네이션;references/metrics.md: 필드 차이 및 단위 변환;references/heuristics.md: 임계값, 계획 및 기울어짐 판단.