はじめに
こんにちは。株式会社High Linkのデータユニットマネージャーの芦川 (@assy) です。
私たちのチームでは、データを強みとした事業価値創出を促進するために、データ基盤の整備やデータマネジメント、全社的なデータ利活用レベルの引き上げに取り組んでいます。
データマネジメントをしていると、「誰が作ったかわからない野良のテーブルが乱立している」ことや「BigQueryコンソール上でviewを定義してしまってコードレビューができない」さらには、「テーブル間の依存関係がわからず削除できない」といった課題にぶつかる方は多いんじゃないでしょうか。
私たちもまさにこのような問題に直面し、導入したのがdbtです。
今回は、dbtの導入に至る経緯や選定の理由、dbtをどう活用しているのかといった話を共有させて頂こうと思います。
私たちのようにデータマネジメントにがっつり人的リソースを割けないスタートアップにおいては、少人数でもメンテナンス可能な仕組みづくりが重要になってきます。
dbtを活用したデータマネジメントについて少しでもご参考になれば幸いです。
dbtとは?
dbt (data build tool) とは、簡単に説明すると ELT (Extract, Load, Transform) の T の部分を担うツールです。
つまり、EL(データ転送)は他のツールに任せ、あくまでBigQuery等Data Warehouseに保存されたデータに対してTransformを行うツールです。
ちなみに私たちはサービスDBデータに対するELをEmbulk 、Tをdbtが担うという構成をとっています。
dbt はテーブルの定義を主にSQLで記述します。SQLが書ければパイプラインを簡単に記述できるのは利点と言えるでしょう。
また、コード内でPython用テンプレートエンジンJinjaを利用することができるため、SQLだけでは記述が難しい処理や、マクロを定義して処理を再利用することも可能です。
GitHubと連携したCI/CDが実現できコードベースの管理ができるのも嬉しいポイント。
dbt導入の経緯
抱えていた課題
私たちは1年ほど前からBigQueryをData Warehouseとして採用し、本格的にデータ基盤の整備に取り組み始めました。
データパイプラインを整備し、BigQuery内のテーブルに対して Lake層、Warehouse層、Mart層 の3段構成を定義し、データマネジメントを行なってきました。
しかしながら、コンソール上で定義したテーブルが増えてくるに従い、次のような問題が露呈してきました。
- コンソール上でテーブル定義を自由にできてしまうため、クエリのレビューの仕組みがない(担当者同士がケアするしかない)
- テーブル定義の変更履歴を管理できない
- テーブル同士の依存関係のトラッキングが大変
- テーブル定義のドキュメントをアドホックに管理するのが大変
特に当時の運用ポリシーでは、事業の担当者がある程度自由にテーブルを増やすことができるようにしていたため、このまま野良のテーブルが増えていくと管理がますます難しくなることは目に見えていました。
こういった課題を解決するために、仕組みの改善が求められました。
なぜdbtを選んだのか
やりたかったこと
- テーブル定義をGitHub上で管理して、CI/CDの基盤を整えたい
- データリネージを構成したい
- ドキュメントを自動生成したい
- なるべくコストを抑えたい
これらを満たすツールを探していたところ、Dataformとdbtが該当し、2択で迷いました。
私たちはBigQueryを利用しているため、Dataformが無料かつ必要十分な機能を備えていたので第一候補に上がりました。
しかしながら2022年9月現在、DataformはGCPへの統合作業が進んでおり、新規サインアップを停止しています。Waitlistに登録しましたがなかなか動きがなかったのでdbtを使うことにしました。
dbtはOSS版(無料)と、dbt cloudというマネージド版(有料)の2種類があります。私たちはdbt自体をメンテナンスするリソース的余裕はなかったため、dbt cloudを選択しました。
dbt cloud はdeveloperアカウント1名までは無料で、チームで利用したい場合、developerアカウント1つにつき月間$50かかります。
まずは個人アカウントではじめてみて、良さそうであればチームアカウントに変更するのがおすすめです。
dbtを活用したテーブル運用ポリシー
dbtの導入と併せて、テーブル管理がしやすくなるよう運用ポリシーの改善を行いました。
具体的には、warehouse層/mart層のテーブルに関しては全てデータエンジニアリングチームがdbtで管理するようにし、野良のテーブルが乱立しないようにしました。
担当者が直接テーブルを生成できないようにすると一定スピード感は落ちますが、データマネジメントチームが管理する対象を明らかにすることで運用をしやすくするメリットのほうが大きいと判断しました。
dbtのコードをGitHubで管理しているため、新しいテーブルを定義する際には必ずコードレビューが入り、品質が担保される仕組みになっています。
また、コミットログが残るため、誰によっていつどのような変更が行われたかは明白です。
dbt活用の工夫
初めて利用する際には dbt公式のチュートリアルから読み始めました。
また、BigQuery向けのチュートリアルとして、以下の記事も非常に参考になりました。
これらを参考にしつつ、実際に運用する上で工夫した点やTipsについてご紹介したいと思います。
ディレクトリ構成
dbt公式ドキュメントのHow we structure our dbt projectsを参考にしつつ、自分たちに合わせて一部改変して構成しています。
├── dbt_project.yml ├── macros └── models ├── source ├── warehouses └── marts
- source … ソースモデルとステージングモデル(データモデリングの最小単位)の定義ファイルを格納
- warehouses … warehouse層に相当するテーブルの定義ファイルを格納
- marts … mart層に相当するテーブル定義ファイルを格納
dbt_project.yml
でディレクトリごとにモデルのconfigを一括定義できるので、カテゴリごとにディレクトリを分けておくと管理が容易になります。
How we structure our dbt projectsについては翻訳、要約してくださっている以下の記事も参考にさせていただきました。 zenn.dev
BigQueryにおけるカスタムスキーマの活用
dbt cloudはデフォルトで、Environment (dbtの実行環境設定) で定義されたデータセットに全てのテーブルを保存します。(後述の target_schema
に相当)
しかしながら、テーブルごとに出力先データセットを制御したいケースは多々あります。
カスタムスキーマを利用すると、モデルごとに保存先データセットを変更することが可能になります。デフォルトでは次の表のように、 <target_schema>_<custom_schema>
ように _
で連結されたデータセット名になります。
Target schema | Custom schema | Resulting schema |
---|---|---|
<target_schema> | None | <target_schema> |
analytics | None | analytics |
dbt_alice | None | dbt_alice |
<target_schema> | <custom_schema> | <target_schema>_<custom_schema> |
analytics | marketing | analytics_marketing |
dbt_alice | marketing | dbt_alice_marketing |
https://docs.getdbt.com/docs/building-a-dbt-project/building-models/using-custom-schemas
実装時はカスタムスキーマを schema
(https://docs.getdbt.com/reference/resource-configs/schema)というconfigで定義します。
models: jaffle_shop: # the name of a project marketing: +schema: marketing
しかしながら、これはあくまで target_schema
は固定されたまま custom_schema
がsuffixになる仕様なので、 custom_schema
自体をデータセット名にしたい場合はうまくいきません。
少し発展的ですが、 generate_schema_name
というmacroを書き換えることで、 custom_schema
が与えられたときのデータセット名生成ルールを変更することが可能です。
例えば、以下のようなコードを macros/get_custom_schema.sql
として配置します。
{% macro generate_schema_name(custom_schema_name, node) -%} {{ generate_schema_name_for_env(custom_schema_name, node) }} {%- endmacro %}
generate_schema_name_for_env
はdbt側が提供している関数で、これを用いることで、 prod
環境のときは custom_schema_name
で与えられたデータセット名になり、それ以外の環境では custom_schema_name
は無視されるようにすることができます。
私たちはこれを利用して出力データセットの設定を行なうようにしています。
Aliasを活用してテーブル名を変更する
dbtはデフォルトではファイル名がテーブル名になります。 alias
configを用いることで、ファイル名に依存せずに保存するテーブル名を自由に設定することができます。
Model | Config | Database Identifier |
---|---|---|
ga_sessions.sql | \<None> | "analytics"."ga_sessions" |
ga_sessions.sql | {{ config(alias='sessions') }} | "analytics"."sessions" |
もちろんカスタムスキーマと併用することも可能です。
これにより任意のデータセットに任意のテーブル名で保存することが可能になります。
-- This model will be created in the database with the identifier `sessions` -- Note that in this example, `alias` is used along with a custom schema {{ config(alias='sessions', schema='google_analytics') }} select * from ...
https://docs.getdbt.com/docs/building-a-dbt-project/building-models/using-custom-aliases
BigQueryのコンソール上でdescriptionを参照できるようにする
dbtは定義ファイルにモデルのdescriptionを記述しておくことで、dbt上で閲覧できるドキュメントを自動生成してくれます。
とはいえ、分析者目線では外部のドキュメントを参照しに行かずともBigQuery上でdescriptionが参照できたほうが便利ですよね。
dbtでは persist_docs
configを有効にすることで実現できます。
例えば dbt_project.yml
に以下のようにconfigを追加します。
models: +persist_docs: relation: true columns: true
https://docs.getdbt.com/reference/resource-configs/persist_docs
relation
を true
にすると、テーブルのdescriptionが反映され、 columns
を true
にするとカラムのdescriptionが反映されます。
Materializationの活用
dbtにはmaterializationという、定義したモデルをData Warehouseに保存する際のテーブル作成方法が設定できます。BigQueryの場合はデフォルトでビューとして保存されます。
こちらはmaterialized
というconfigで設定が可能です。
models: jaffle_shop: +materialized: table example: +materialized: view
https://docs.getdbt.com/docs/building-a-dbt-project/building-models/materializations
- View: ビューとして保存する
- Table: 実体テーブルとして保存する
- Incremental: 前回の
dbt run
からの差分更新を行う - Ephemeral: モデル定義はするがデータウェアハウスに反映したくない場合に利用
基本的にはViewで構成していますが、ユーザー行動データのようなストリーミングで日々増えていくデータに対応するwarehouse層のテーブルを定義する際にはincremental modelを活用しています。こちらの詳細は別の記事でご紹介できればと思います。
さいごに
dbtを導入し、開発・運用のフローを整備することでチームでのデータマネジメントは格段にやりやすくなりました。
私たちのようなスタートアップでは特に、データマネジメントに大きなリソースを割くことは難しいです。だからこそ早い段階から小規模チームでも運用可能な体制を整備することは、中長期的には大きな一歩になると考えています。
実際に使ってみた感想としては、dbtは多機能ですが銀の弾丸ではなく、利用者側の工夫や学習がある程度必要なものであると感じました。
しかしながら、dbtを導入することはただ管理がしやすくなる以上に、チームで共通のツールを採用し、プロセスを統一化できることに大きな価値があると思います。
実際、dbtを導入してからは、dbtを軸にデータマネジメントの議論が盛んに行われるようになりました。 この点において、dbtを導入するという意思決定は非常によかったと感じています。
High Linkではデータ基盤の整備やデータマネジメントを通して、一緒に全社的なデータ利活用レベルを引き上げていけるエンジニアを募集しております!
https://herp.careers/v1/highlink/RIGo8XhyyCPQ?utm_source=hatena&utm_medium=blog&utm_campaign=dbt-data-managementherp.careers