Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2025-02-21 Tokyo dbt Meetup#12 Google Cloudではじめ...

2025-02-21 Tokyo dbt Meetup#12 Google Cloudではじめるdbt python model

Tokyo dbt Meetup #12での発表資料
前半では弊社のデータパイプラインのアーキテクチャ概要とdbt導入のメリット、特にdbt python modelの活用事例(ReverseETL、外部APIからのデータ収集など)について説明し、
後半ではDataProc ServerlessでのPySpark活用方法や実践的な運用に関する10のTipsを紹介しています。

Avatar for Kentaro Yoshida

Kentaro Yoshida

February 21, 2025
Tweet

More Decks by Kentaro Yoshida

Other Decks in Technology

Transcript

  1. © Commune Inc. All rights reserved 1 Google Cloudではじめるdbt python

    model Commune Inc. Senior Data Engineer Kentaro Yoshida DataProc ServerlessでのPySpark活⽤事例 2025/02/21 Tokyo dbt Meetup #12
  2. © Commune Inc. All rights reserved ⾃⼰紹介 Kentaro Yoshida (X:

    @yoshi_ken) 3 Communeのデータエンジニア。ex-TreasureData • 2024年6⽉にコミューンへ⼊社 • Product & Dataチームに所属(10⼈くらい) • ビジネスに付加価値を与える可⽤性の⾼い安定的 なデータ収集をアーキテクチャ設計から推進。 データ処理にdbtを活⽤、BIにThoughtSpot導⼊中 • ⾃社メディア事業をいくつも起ち上げてきた ソフトウェアエンジニアの経験を⽣かし、 2015年頃からはデータ分析基盤を軸に、事業系 データエンジニアをエンジョイしています
  3. © Commune Inc. All rights reserved ⽬次 1. はじめに ◦

    弊社のデータパイプラインのアーキテクチャ図 ◦ dbtを導⼊して良かったこと ◦ dbt python modelのユースケース 2. dbt python model⼊⾨ ◦ GoogleCloudで掛かっているコスト ◦ 導⼊の背景 ◦ dbt python modelを導⼊して良かったこと 3. dbt python model実践編 ◦ 良いところ ◦ イケてない所‧対処法 ◦ ハマった所‧対処法 4. 運⽤Tips、まとめ
  4. © Commune Inc. All rights reserved 8 dbtを導⼊して良かったこと 動作検証されたものが本番リリースされる仕組みが整ったことで、データ不具合に⾒舞われな い体制となりました。

    • データの整形‧変換作業の効率化 ◦ 依存関係に応じた実⾏順序を担保できるようになった ◦ dbt buildによりテストに通ってから次のモデルを作り始めるため、 下流モデルへ壊れたデータが伝播していくことがなくなった ◦ 定型的な処理をJinja Macroに寄せることで、⼈的な運⽤を激減できた • データパイプラインの可視化と管理(dbt exposure) • Slim CI/CDの導⼊によって、コードの品質管理が⾏き届くようになった • ローカルではdbt core、プロダクションとCI/CD環境ではdbt Cloudを併⽤ • SQLでは表現しきれないことを、dbt python modelを利⽤することで依存関係含めて解 決できた
  5. © Commune Inc. All rights reserved • dbtの仕組みの中で、作成したレコードへのunit testを掛けてデータ品質を保てる •

    ReverseETLの場合は処理した結果のログを結果として格納し、それが期待する処 理内容であったかを同様にテストできる。処理対象⾏数の異常値検出なども可能 • dbtの仕組みの中で、CI/CDを回せる GitHubのPRを作りテストにパスしていたらマージする流れを同様に回せる • ローカル環境でも、pythonインタプリタでpysparkセッションを作って試せる • ちょっとしたクローラー(スクレイピング)のコードが短く表現できる ◦ Spark 4.0が出て、Python Data Source API が使えるようになったら外部API からの取り込みがカプセル化され、さらに使いやすくなる未来が⾒えている 9 dbt python modelの良いところ
  6. © Commune Inc. All rights reserved • Redashでどのようなクエリを実⾏しているか、クエリの⼀覧をBigQueryに転送 ◦ BigQueryでのJob実⾏履歴と結合して、リネージュに組み込み(dbt

    exposure) • 外部提携メディアのキャンペーン⼀覧をAPIで収集 ◦ リスト⼀覧を取った後に、詳細取得APIの結果を並列処理で収集 • SalesforceへのReverseETL ◦ Salesforceへ顧客毎の利⽤量をupsert()で書き出し 10 dbt python modelのユースケース
  7. © Commune Inc. All rights reserved 14 dbt python modelはdbtにどんな変化を与えるか?

    ※What, exactly, is dbt?より引用 dbt python modelはSQLやJinjaだけのTransformの範囲では難しかった領域をカバーできる
  8. © Commune Inc. All rights reserved • DataProc Serverlessは 低コスト、インフラ管理不要

    • 標準構成は、2台、2 Core、メモリ16GB • 仮に、1回 3分で終わるタスクを 31⽇間動かすと、⽉額 約128円 • Sparkによる分散処理の最適化 例: リストを取ってきて、それの中⾝を個 別にAPIで収集するとき、よしなに分散処 理してくれる • Sparkは後⽅互換性が⾼く、 ⻑期にわたって保守しやすい 16 GoogleCloudで掛かっているコスト 週に1度、2つのJobを毎週実行している:月額 39円
  9. © Commune Inc. All rights reserved ひとりデータエンジニアで、データパイプラインの運⽤を⾏っている • dbtを主軸としていて、バッチ基盤をイチから構成するニーズが薄い •

    dbtで回る仕組みの中で、⼩さな⼿間で安定的に動く仕組みが欲しかった • 1回の処理に数分かかっても、全体の処理時間からしたら誤差の範囲 • リトライが必要な時、依存するモデル含めた再実⾏、誰でも対応可能 18 導⼊の背景
  10. © Commune Inc. All rights reserved • シェルスクリプトによる時間ベースの実⾏制御 ◦ 「20分で終わる想定の処理」に対し、30分後に次のジョブを設定

    ◦ データ量増加や処理の複雑化で実⾏時間が延び、パイプラインが破綻 • スクリプト間の連携の難しさ ◦ 空データや品質の悪いデータの混⼊ ◦ エラーハンドリングの複雑化 • Pythonスクリプトの管理‧テストの課題 ◦ dbtで運⽤しているデータ品質担保の仕組みやCIをそのまま適⽤したい ◦ たまにしか変更しないプログラムを触る⼼理的ストレスを下げたかった これら、dbt python modelで全て解決可能 19 データ収集バッチの実⾏管理を⾏う際に考慮すべき観点
  11. © Commune Inc. All rights reserved 21 出典:Apache Spark の紹介(前半:Sparkのキホン)

    https://www.slideshare.net/slideshow/apache-spark-spark/35286620#2
  12. © Commune Inc. All rights reserved 22 Google Cloudにおける、dbt python

    modelの動作原理 インメモリ並列処理基盤
  13. © Commune Inc. All rights reserved 23 • 実⾏フロー ◦

    Pythonコードをdbtが1ファイルのテンプレートに固めてGCSに配置 ◦ DataProc Serverlessを起動して、GCSからスクリプトを読み込む ◦ ユーザーコードをSparkコンテキストで実⾏ ◦ 結果レコードをBigQueryに保存 • 重要なポイント ◦ dbt⾃体はDataProc上で実⾏されない ◦ pipライブラリのリストrequirments.txtなどは特に⾒ない ◦ incrementalモデルを使うと実⾏結果を積み上げられる Google Cloudにおける、dbt python modelの動作原理
  14. © Commune Inc. All rights reserved • DataProc Serverlessの起動まで都度、1分半ほど掛かる •

    連続的に回すならDataProcクラスタを先に⽴ち上げた⽅が良い submission_method= "cluster", # default: serverless dataproc_cluster_name= "dbt-pyspark-cluster" , # Dataprocクラスタの名前 • dbt Cloudの⽇次バッチが動く間だけDataProcクラスタを起動するなら、 次の仕組みが取れます ◦ Cloud Scheduler + Cloud FunctionでDataProcクラスタを⽴ち上げたら、 dbt Cloud Job (DataProc)をAPI Triggerで呼び出す ◦ JOb完了時にdbt Cloud JobからWebHookでCloud Functionを呼び出して、 DataProcクラスタを終了させる 24 DataProc Serverless か DataProc Batch を使うか
  15. © Commune Inc. All rights reserved 使い始める前に考慮したい観点 • pandasで数⾏なんだけど →

    dbt Macroを活⽤したら解決できるか検討しよう • BigQueryの無料オプション、DataTransferServiceで対応できるか検討しよう Salesforce, Marketing Cloud, Ad系のデータ収集もその仕組みでカバー可能 • AWS StepFunctionやAWS EventBridge、Google Integration Connectorsを検討で きるエンジニアリングチーム体制がある • GoogleのServiceAccountで操作できない、個⼈クレデンシャルを利⽤するよう な、スプシ書き出しはフルスクラッチ開発⼯数に⾒合わない ◦ 標準機能のGoogle Connected Sheetを使おう ◦ Census、Hightouch、TROCCOといったReverseETL機能のある製品を検討しよう ◦ BIの機能でできるかも。Looker, ThoughtSpotも検討しよう 25 dbt python modelがフィットしないシチュエーション
  16. © Commune Inc. All rights reserved • データ取り込み‧データ変換 ◦ pandasなら数⾏だが、SQLでは明らかに複雑性が増してしまうもの

    ▪ 時系列データの⽋損値補完 NaNを前後の値から補間するinterpolate()メソッド ◦ JupyterNotebookで⾏える程度のちょっとしたスクレイピング ▪ PyPIとbackoffデコレータでリトライ機構を持てば回せそうな要件 ▪ AWS Glue、AWS EventBridgeを運⽤する程ではない規模感 ◦ Sparkが得意とするような領域、MLまわりの処理 • データ出⼒ ◦ レコードを外部APIにuploadしてバッチ処理を⾛らせる 例: Salesforce Update() SOAP API, Salesforce Upsert() SOAP API 27 dbt python modelがフィットするユースケース
  17. © Commune Inc. All rights reserved 29 ⾏うこと • dbt

    python modelの中で⾏う事は最⼩限とする ◦ 前処理のJOINを済ませて、欲しい形式にしてから読み出す ◦ SQLで出来ることは意地でも先に済ませておこう • クリーンなコードの書き⽅の型を作ってベストプラクティスを共有し、 それを参考にAIコーディングしたら似たような書き⽅で⽣成できる • dbtのテストを活⽤して、データに異常が無いことを他のモデルと同様に担保 • 単⼀責任の原則を守り、DRYなコードを⼼がけること 結果 • 壊れにくい、⻑期の運⽤がしやすいコードとなる メンテナンスできる品質のコードをどのように管理するか?
  18. © Commune Inc. All rights reserved 1. profiles.ymlやdbt CloudのEnvironmentsでの定義⽅法 2.

    PySparkでの簡易なログ出⼒ 3. PySparkのローカル環境での動かし⽅ 4. バージョンを固定したpython libraryのインストール⽅法 5. APIキーなどの接続情報をどのように渡すか? 6. 変数の渡し⽅はschema.yml経由のみ 7. SQLよりも⻑いタイムアウトを設定したい 8. CIの時は読み込むデータや書き込み先を変えたい 9. BigQueryテーブルへ書き出す際のデータ型を固定する⽅法 10. パフォーマンスチューニング 31 運⽤Tips
  19. © Commune Inc. All rights reserved • targetを使い分けた⽅が運⽤しやすい dbt run

    –select “hoge” –-target pyspark-dev • spark.**.**の数値はクォート必須 • dbt CloudでEnvironmentを作れば、処理の 負荷に合わせたリソース割り当てが可能 32 運⽤Tips1: profiles.ymlでの定義⽅法
  20. © Commune Inc. All rights reserved • DataProc Serverlessを⽴ち上げるならdbt runするだけ

    • ローカルの対話シェルで試しに動かす際は、次のようにSparkのセッションを作成 • そして、def model()の中⾝をインタラクティブに実⾏することで、 データの収集のステップ実⾏や、外部へのReverseETLの処理のテストが⾏える 34 運⽤Tips3: PySparkのローカル環境での動かし⽅
  21. © Commune Inc. All rights reserved 35 • Serverlessだと、⾃前のイメージファイルで⽴ち上げられないため •

    Pythonファイル1つだけ送られる仕様のため、都度インストールする必要がある ◦ requirements.txtやpyproject.tomlが使えないということ ◦ バージョン指定付きでインストールする → 突然動かなくなることを未然に防ぐ 運⽤Tips4: バージョンを固定したpython libraryのインストール⽅法
  22. © Commune Inc. All rights reserved • dbt CloudのDBT_ENV_SECRET_** 環境変数は使えない

    ◦ これはprofiles.ymlやpackages.ymlだけで使うもの • 環境変数やvarから平⽂で渡すと、どうなるか? ◦ DataProcに渡す際にGCSに置かれるpythonコードの中に平⽂で書かれます → セキュリティ上ダメ、絶対 Google Secret Managerを使おう 36 運⽤Tips5: Google Cloudにおける、クレデンシャルの管理⽅法
  23. © Commune Inc. All rights reserved • job_execution_timeout_seconds を超えるとエラー ◦

    通常のSQLのタイムアウトと同じ時間でdbt側は失敗したと判定して終了 ◦ ところがDataProcのJobは動いたまま、そのまま正常終了する ◦ → schema.ymlにてconfig.timeoutを⽤いてタイムアウト設定を上書きしよう 38 運⽤Tips7: SQLよりも⻑いタイムアウトを設定したい タイムアウトを上書きする設定
  24. © Commune Inc. All rights reserved • schema.ymlのconfigで、env_var()を使うとstate:modifiedに毎回引っかかる ◦ CIで毎回処理対象となりコストがかさむことに

    • target.nameを⽤いて、CIであるかどうかを⾒分ける対処で解決 ◦ dbt CloudのCI Jobのtarget_nameの設定を⾏う必要がある ◦ これでいける 39 運⽤Tips8: CIの時は読み込むデータや書き込む先を変えたい env_varはschema.ymlに⼊れる使い⽅はやめた⽅が良い
  25. © Commune Inc. All rights reserved • Pandasを経由すると、null値を持つ数 値型がfloatになったり、値が変化する のでSparkの流儀に倣う⽅が吉

    • 関数をUDF化し、返り値の型を渡す @F.udf(returnType=schema) • StructTypeを使って配列型に対応可能 (BigQueryで⾔うRECORD型) • JSONやtimestampは⼀旦String型に • timestampはBQへ書き込む前に変換 40 運⽤Tips9: 書き出す際のデータ型を固定する⽅法
  26. © Commune Inc. All rights reserved • 並列化したいところを関数化します • ⼊⼒データをパーティション化して、並列実⾏できるようにしよう

    .repartition(8)といった形で、executorの数 × cores × 2〜3が⽬安 ⼩さくすることで、偏りを防ぐ意味合いもあります。 • 並列処理を使うため、件数を絞ってテストするときは .limit(32).repartition(8) のように、 Limit句を先に、パーティショニングを必ず後に書こう • ⼀部のスクリプトのみ割り当てリソースを変えるには、Environmentを使い分けよう • 右の設定だと、2台で4処理、8並列で⾛る • プロファイリングも有効にするとなお良し runtime_config: properties: spark.executor.instances: '2' spark.executor.cores: '4' spark.executor.memory: 6g spark.driver.cores: '4' spark.driver.memory: 4g dataproc.profiling.enabled: "TRUE" dataproc.profiling.name: "dbt-user" 41 運⽤Tips10: パフォーマンスチューニング
  27. © Commune Inc. All rights reserved 簡易に達成できるメリットが多く、⼩規模なチームが⼩さく始めるのにも最適! • 実⾏時間の変動があっても、dbtなら依存関係を壊さず実⾏してくれる •

    バッチを再実⾏したら、その後の処理も綺麗に再実⾏される • dbtのリネージュの⼀つに組み込まれる • 取り込みに失敗しても、失敗したところからのリトライがdbtなら容易に出来る • PySparkのコードはAIに書いてもらえば、ほぼほぼ完成形に近いものが作れる • 運⽤ハードルがぐっと下がり、dbtが使える⼈に安⼼して任せられる物となる 43 まとめ
  28. © Commune Inc. All rights reserved • BI + レポート出⼒機能のあるものを検討しよう

    • GoogleSheet, Salesforce, Gainsight, ServiceNow, Zohoなど対応 • ミニマムだと、ThoughtSpot Teamプラン $95/⽉ @AWS Marketplace 45 BI + レポート出⼒機能のあるものを使っても、ReverseETLができる