Community연구 & 데이터 분석github.com

Spark SQL 진단

Spark SQL 진단 스킬은 Apache Spark/Spark SQL 작업의 실행 상태를 분석합니다. SQL 원문, EXPLAIN FORMATTED, Kyuubi/Spark Driver 실행 로그, Spark UI 주소를 활용하여 느린 쿼리 병목, 데이터 기울어짐, spill, GC, 스케줄링/콜드 스타트, 조인 팽창 및 설정 문제를 진단합니다.

Spark SQL 진단란 무엇인가요?

이 스킬은 Apache Spark SQL 작업의 성능 문제를 종합적으로 진단합니다. 사용자는 Spark UI 주소, SQL 원문, EXPLAIN FORMATTED 출력, Kyuubi 또는 Spark Driver 로그 등을 제공할 수 있으며, AI는 이를 분석하여 느린 쿼리의 원인이 스캔, 셔플, 조인, 집계, spill, GC, 스케줄링, 콜드 스타트 중 어느 계층인지 파악합니다. 또한 데이터 기울어짐이 발생한 stage/task/SQL 조각을 식별하고, 해당 문제가 데이터, 리소스 또는 설정 중 어디에서 기인하는지 진단합니다. 이 스킬은 CLI 기반 스크립트(`spark_diagnose.py`)를 실행하여 Spark REST API에서 상세 메트릭을 수집하고, 구조화된 JSON 및 마크다운 보고서를 생성합니다. 주요 기능으로는 stage 타임라인 분석, task 분포 통계, 진성 데이터 기울어짐과 콜드 스타트 구분, spill 탐지, 그리고 SQL 계획 매핑이 포함됩니다. 최종 보고서는 SQL 의미를 반영하여算子에서 SQL 조각으로의 매핑, 핫 키의 비즈니스 의미 추론, 우선순위와 예상 효과, 그리고 외부 검증이 필요한 부분을 명확히 표기합니다.

지원 대상~Claude Code~Codex CLI~Cursor
npx skills add 12-twelve-ly/spark-sql-diagnosis-skill

Installed? Explore more 연구 & 데이터 분석 skills: affaan-m/uspto-database, affaan-m/scholar-evaluation, affaan-m/literature-review · View all 6 →

즐겨 사용하는 AI에게 물어보기

이 에이전트 스킬이 미리 로드된 새 채팅을 엽니다.

문서

Spark SQL 진단은(는) 무엇을 하나요?

사용 시기

사용자가 다음 조합 중 하나를 제공할 때 사용하세요:

  • Spark UI / History Server / YARN proxy 주소;
  • Spark SQL과 그 EXPLAIN FORMATTED;
  • Kyuubi / Spark Driver 실행 로그;
  • /api/v1/...에서 내보낸 JSON 또는 event log.

목표는 "몇 가지 지표를 보는 것"이 아니라, 다음 질문에 답하는 것입니다:

  1. 이 쿼리가 느린 계층은 무엇인가: 스캔, 셔플, 조인, 집계, spill, GC, 스케줄링, 콜드 스타트;
  2. 데이터 기울어짐이 있는가, 있다면 어떤 stage / task / SQL 조각에서 발생하는가;
  3. 무엇이 데이터 문제이고, 무엇이 리소스 또는 설정 문제인가;
  4. 다음 단계는 SQL 수정, 설정 변경, 또는 데이터 보충 중 무엇인가.

입력 우선순위

입력할 수 있는 작업
UI 주소 + Execution ID/제출 시간 + SQL가장 완전, task 수준 진단
실행 로그 (app ID 및 UI 주소 포함) + SQL로그를 먼저 분석한 후 UI 접근; UI를 사용할 수 없으면 stage 수준으로 다운그레이드
EXPLAIN FORMATTED계획 구조와 SQL 조각 매핑만 가능
event log / History ServerUI 만료 후의 보완책

로그에는 일반적으로 다음이 이미 포함되어 있습니다:

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 executorRunTime vs 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/테이블 생성 로직에서 추론 가능한 경우);
  • 권장 사항의 우선순위와 예상 효과;
  • "외부 검증 필요" 부분을 명확히 표기.

보고서 구조:

  1. 결론 우선 순서 (영향 순);
  2. 실행 개요 및 타임라인;
  3. 기울어짐/긴 꼬리 증거 테이블;
  4. SQL 계획 매핑;
  5. 설정 및 리스크;
  6. 권장 사항;
  7. 증거 출처 및 한계;
  8. 여전히 외부 검증이 필요한 문제.

핵심 판단 규칙

다음 규칙을 반드시 준수하여 가장 흔한 오판을 피해야 합니다:

  1. 기울어짐은 records와 duration을 보고, shuffle bytes만 보지 마십시오. 압축 가능성이 높은 핫 키 (예: 많은 item_id=1)는 몇 MB에 불과할 수 있지만, records 수는 60%를 차지합니다.

  2. 진성 기울어짐과 콜드 스타트를 구분하십시오. 느린 task의 records 수는 정상이지만 executorDeserializeTime / duration이 높다면, 이는 데이터 기울어짐이 아니라 콜드 executor입니다.

  3. 부분 집계가 GROUP BY 기울어짐을 가릴 수 있습니다. 계획에 partial_count / partial_sum이 있는 경우, 핫 키는 셔플 전에 소량의 행으로 압축됩니다. 집계 작성 방식 자체가 기울어짐을 회피했는지 확인해야 합니다.

  4. count(DISTINCT)는 2단계 중복 제거입니다. 첫 번째 셔플의 키는 일반적으로 distinct 필드 (예: (item_id, buyer_id))를 포함하므로, 핫 키가 분산됩니다. 일반 GROUP BY로 판단하지 마십시오.

  5. AQE skew join은 크기 기반입니다. 판단 기준은 압축된 파티션 크기와 skewedPartitionFactor / skewedPartitionThresholdInBytes입니다. 압축 가능한 핫 키는 임계값보다 낮아 분할되지 않을 수 있습니다.

  6. 셔플 파티션 수를 늘려도 단일 hot key는 희석되지 않습니다. 단일 키는 항상 하나의 파티션으로 이동합니다. 파티션이 많을수록 다른 파티션은 더 작아지고, max/median은 오히려 커집니다.

  7. Stage wall clock이 task 실행 시간보다 훨씬 크면, 먼저 스케줄링을 확인하십시오. launchTime - submissionTime, 동적 할당 minExecutors, YARN 큐를 확인하세요.

  8. 조인의 출력 행 수가 입력 행 수보다 현저히 클 때만 팽창을 의심하십시오. 출력 행 수가 사실 테이블의 행 수와 같다면, 문제는 일반적으로 분포이지 중복 키 때문이 아닙니다.

경계

  • 실제 데이터 내용은 볼 수 없습니다. 핫 키의 구체적인 값은 사용자가 데이터를 확인해야 합니다.
  • YARN 큐 대기, 컨테이너 할당 지연의 구체적인 원인은 RM/Kyuubi 로그가 필요합니다.
  • UDF/사용자 정의 코드 문제는 코드와 executor 로그가 필요합니다.
  • UI/event log가 없는 경우, 일반 driver 로그는 stage 수준 진단만 가능합니다.
  • SQL을 실행하지 않고, 데이터를 수정하지 않으며, cookie/token을 출력하지 않습니다.

참고

  • references/endpoints.md: REST 엔드포인트 및 페이지네이션;
  • references/metrics.md: 필드 차이 및 단위 변환;
  • references/heuristics.md: 임계값, 계획 및 기울어짐 판단.

관련 스킬