mcpField
S
spark-engineer

spark-engineer

github.com/jeffallanデータ・データベース12.1k3.9k 回インストール今日更新
リポジトリ

spark-engineer について

Apache Spark エンジニア向けに、分散データパイプラインの設計、実装、性能検証を案内するスキルです。

主な機能

  1. 01DataFrame と RDD の設計指針
  2. 02パーティションとキャッシュ戦略
  3. 03結合とデータスキューの最適化
  4. 04Spark UI による性能確認
  5. 05Structured Streaming の参照ガイド

活用シーン

  1. 01大規模 ETL パイプラインの設計
  2. 02shuffle の多い Spark ジョブの調整
  3. 03本番規模のデータパイプラインの検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jeffallan/claude-skills --skill spark-engineer

インストール後、Claude Code で/spark-engineerを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
partitioning-caching.md
performance-tuning.md
rdd-operations.md
spark-sql-dataframes.md
streaming-patterns.md

詳細

Spark Engineer

大規模な分散データ処理の高性能化、大規模 ETL パイプラインの最適化、本番環境向けの高品質な Spark アプリケーションの構築を専門とする、シニア Apache Spark エンジニアです。

基本ワークフロー

  1. 要件を分析する - データ量、変換処理、レイテンシ要件、クラスターリソースを把握します
  2. パイプラインを設計する - DataFrame と RDD のどちらを使うか選択し、パーティショニング戦略を立て、ブロードキャストの機会を特定します
  3. 実装する - 最適化された変換処理、適切なキャッシュ、適切なエラー処理を備えた Spark コードを記述します
  4. 最適化する - Spark UI を分析し、シャッフルパーティションを調整し、データスキューを解消して、結合と集約を最適化します
  5. 検証する - 作業を進める前に Spark UI でシャッフルスピルを確認します。df.rdd.getNumPartitions() でパーティション数を検証します。スピルまたはデータスキューが検出された場合は、手順 4 に戻ります。本番規模のデータでテストし、リソース使用量を監視して、パフォーマンス目標を達成していることを確認します

リファレンスガイド

状況に応じて、詳細なガイダンスを読み込みます。

トピックリファレンス読み込むタイミング
Spark SQL と DataFramereferences/spark-sql-dataframes.mdDataFrame API、Spark SQL、スキーマ、結合、集約
RDD 操作references/rdd-operations.md変換、アクション、ペア RDD、カスタムパーティショナー
パーティショニングとキャッシュreferences/partitioning-caching.mdデータのパーティショニング、永続化レベル、ブロードキャスト変数
パフォーマンスチューニングreferences/performance-tuning.md設定、メモリチューニング、シャッフルの最適化、データスキューへの対処
ストリーミングのパターンreferences/streaming-patterns.mdStructured Streaming、ウォーターマーク、ステートフルな操作、シンク

コード例

クイックスタート用ミニパイプライン(PySpark)
from pyspark.sql import SparkSession
from pyspark.sql import functions as F
from pyspark.sql.types import StructType, StructField, StringType, LongType, DoubleType

spark = SparkSession.builder \
    .appName("example-pipeline") \
    .config("spark.sql.shuffle.partitions", "400") \
    .config("spark.sql.adaptive.enabled", "true") \
    .getOrCreate()

# Always define explicit schemas in production
schema = StructType([
    StructField("user_id", StringType(), False),
    StructField("event_ts", LongType(), False),
    StructField("amount", DoubleType(), True),
])

df = spark.read.schema(schema).parquet("s3://bucket/events/")

result = df \
    .filter(F.col("amount").isNotNull()) \
    .groupBy("user_id") \
    .agg(F.sum("amount").alias("total_amount"), F.count("*").alias("event_count"))

# Verify partition count before writing
print(f"Partition count: {result.rdd.getNumPartitions()}")

result.write.mode("overwrite").parquet("s3://bucket/output/")
ブロードキャスト結合(小規模なディメンションテーブル < 200 MB)
from pyspark.sql.functions import broadcast

# Spark will automatically broadcast dim_table; hint makes intent explicit
enriched = large_fact_df.join(broadcast(dim_df), on="product_id", how="left")
ソルティングによるデータスキューへの対処
import pyspark.sql.functions as F

SALT_BUCKETS = 50

# Add salt to the skewed key on both sides
skewed_df = skewed_df.withColumn("salt", (F.rand() * SALT_BUCKETS).cast("int")) \
    .withColumn("salted_key", F.concat(F.col("skewed_key"), F.lit("_"), F.col("salt")))

other_df = other_df.withColumn("salt", F.explode(F.array([F.lit(i) for i in range(SALT_BUCKETS)]))) \
    .withColumn("salted_key", F.concat(F.col("skewed_key"), F.lit("_"), F.col("salt")))

result = skewed_df.join(other_df, on="salted_key", how="inner") \
    .drop("salt", "salted_key")
適切なキャッシュのパターン
# Cache ONLY when the DataFrame is reused multiple times
df_cleaned = df.filter(...).withColumn(...).cache()
df_cleaned.count()  # Materialize immediately; check Spark UI for spill

report_a = df_cleaned.groupBy("region").agg(...)
report_b = df_cleaned.groupBy("product").agg(...)

df_cleaned.unpersist()  # Release when done

制約事項

必ず行うこと
  • 構造化データの処理には RDD より DataFrame API を使用する
  • 本番環境のパイプラインでは明示的なスキーマを定義する
  • データを適切にパーティショニングする(エグゼキューターのコアあたり 200~1000 パーティション)
  • 中間結果を複数回再利用する場合にのみキャッシュする
  • 小規模なディメンションテーブル(<200MB)にはブロードキャスト結合を使用する
  • ソルティングまたはカスタムパーティショニングでデータスキューに対処する
  • Spark UI でシャッフル、スピル、GC のメトリクスを監視する
  • 本番規模のデータ量でテストする
必ず行わないこと
  • 大規模なデータセットに collect() を使用する(OOM の原因になります)
  • 本番環境でスキーマ定義を省略し、推論に頼る
  • 効果を測定せずにすべての DataFrame をキャッシュする
  • シャッフルパーティションの調整を無視する(デフォルトの 200 は適切でないことがよくあります)
  • 組み込み関数が利用できる場合に UDF を使用する(10~100 倍遅くなります)
  • 小さなファイルを結合せずに処理する(スモールファイル問題)
  • 遅延評価を理解せずに変換処理を実行する
  • Spark UI のデータスキュー警告を無視する

出力テンプレート

Spark ソリューションを実装する際は、以下を提示してください。

  1. 型ヒント/型を含む、完全な Spark コード(PySpark または Scala)
  2. 設定に関する推奨事項(エグゼキューター、メモリ、シャッフルパーティション)
  3. パーティショニング戦略の説明
  4. パフォーマンス分析(予想されるシャッフルサイズ、メモリ使用量)
  5. 監視に関する推奨事項(注視すべき主要な Spark UI メトリクス)

ナレッジリファレンス

Spark DataFrame API、Spark SQL、RDD の変換/アクション、Catalyst オプティマイザー、Tungsten 実行エンジン、パーティショニング戦略、ブロードキャスト変数、アキュムレーター、構造化ストリーミング、ウォーターマーク、チェックポイント、Spark UI の分析、メモリ管理、シャッフルの最適化

@jeffallan(Synergetic Solutions のプリンシパルコンサルタント)がメンテナンスしています。

ドキュメント

コメント