Community研究&データ分析github.com

12-twelve-ly/spark-sql-diagnosis

Apache Spark / Spark SQL タスクの実行状況を分析します。SQL原文、EXPLAIN FORMATTED、Kyuubi/Spark Driver 実行ログ、Spark UI アドレスから、遅いクエリのボトルネック、データ偏り、スピル、GC、スケジューリング/コールドスタート、結合爆発、構成問題を特定します。トリガーワード:Spark UI、SparkUI、Spark SQL 分析、SQL 遅い、データ偏り、ステージ遅い、タック長尾、Spark タスク診断。

spark-sql-diagnosis とは?

このスキルは、Apache Spark / Spark SQL のパフォーマンス問題を診断するためのプロフェッショナルツールです。ユーザーが提供する Spark UI アドレス、SQL文とそのEXPLAIN FORMATTED、Kyuubi/Spark Driver 実行ログ、または event log を入力として、クエリの遅延原因を特定します。単に指標を確認するだけでなく、スキャン、シャッフル、結合、集計、スピル、GC、スケジューリング、コールドスタートのどの層で問題が発生しているのか、データ偏りの有無とその発生箇所、問題がデータ起因なのかリソース/構成起因なのかを分析し、SQL修正、構成変更、データ補完のいずれが適切かをアドバイスします。Claude CodeやCursorなどのAIエージェント上で動作し、付属のPythonスクリプトを用いてREST APIから詳細な実行時データを取得し、構造化された診断レポートを生成します。

対応~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. このクエリのどの層が遅いのか:スキャン、シャッフル、結合、集約、スピル、GC、スケジューリング、コールドスタート;
  2. データ偏りはあるか、どのステージ / タスク / SQL 断片で発生しているか;
  3. データの問題か、リソースまたは構成の問題か;
  4. 次に取るべきアクションは、SQL の修正、構成の変更、データの補完のどれか。

入力の優先順位

入力できること
UI アドレス + Execution ID/送信時間 + SQL最も完全、タスクレベルの診断
実行ログ(app ID と UI アドレスを含む)+ SQLまずログを解析し、次に UI にアクセス;UI が利用不可の場合はステージレベルにダウングレード
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、ステージ/ジョブのタイムライン、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 と Markdown を出力します。重点的に確認する項目:

  • ステージタイムライン:ウォールクロック vs executorRunTime vs タスク起動遅延;
  • タスク分布:duration、records、shuffle bytes の max/median/p95;
  • 真の偏り:1つのタスクの records と duration が同時に中央値を大幅に上回る;
  • 偽の長尾:タスクのレコード数は正常だが、executorDeserializeTime が非常に高い、通常はコールド executor;
  • スピル: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 しか占有しないが、レコード数は 60% を占める可能性がある。

  2. 真の偏りとコールドスタートを区別する。 遅いタスクでレコード数が正常で executorDeserializeTime / duration が非常に高い場合、それはコールド executor であり、データ偏りではない。

  3. 部分集約は GROUP BY の偏りを隠す。 計画に partial_count / partial_sum がある場合、ホットキーはシャッフル前に少数の行に圧縮される。集約の書き方自体が偏りを回避しているかどうかを確認する。

  4. count(DISTINCT) は二段階の重複排除。 最初のシャッフルのキーは通常 distinct フィールド(例:(item_id, buyer_id))を含むため、ホットキーは分散される。通常の GROUP BY のように判断しない。

  5. AQE skew join はサイズベース。 判断基準は圧縮後のパーティションサイズと skewedPartitionFactor / skewedPartitionThresholdInBytes。圧縮可能なホットキーはしきい値を下回り、分割されない可能性がある。

  6. シャッフルパーティション数を増やしても、単一のホットキーは希釈されない。 単一のキーは常に1つのパーティションに移動する。パーティション数が多いほど他のパーティションは小さくなり、max/median はむしろ大きくなる。

  7. ステージのウォールクロックがタスク実行時間を大幅に上回る場合、まずスケジューリングを確認する。 launchTime - submissionTime、動的割り当て minExecutors、YARN キューを確認。

  8. 結合の出力行数が入力行数を大幅に上回る場合にのみ、爆発を疑う。 出力行数がファクトテーブルの行数と等しい場合、問題は通常分布であり、重複キーではない。

境界

  • 実際のデータ内容は見えない。ホットキーの具体的な値はユーザーがデータを確認する必要がある;
  • YARN キュー待ち、コンテナ割り当ての遅さの具体的な原因は RM/Kyuubi ログが必要;
  • UDF/カスタムコードの問題にはコードと executor ログが必要;
  • UI/event log がない場合、通常の driver ログではステージレベルの診断しかできない;
  • SQL を実行しない、データを変更しない、cookie/token を表示しない。

参考

  • references/endpoints.md:REST エンドポイントとページネーション;
  • references/metrics.md:フィールドの違いと単位換算;
  • references/heuristics.md:しきい値、計画、偏り判定。

関連スキル