はじめに
この記事はBrainPad Advent Calender 19日目の記事です。
本日はdbt (data build tool)について書かせていただこうと思います。
dbtは、ETLのtransformのワークフローをいい感じに管理してくれるツールです。
日本語でも既にたくさんの分かりやすい資料が公開されていますので、一般的な説明はそちらにお任せして割愛します。(dbtとは?など)
主にデータエンジニアの方々の中で広がっている印象を受けるdbtですが、本記事はデータサイエンティストも分析の現場で導入する価値があるのではないかという話をさせていただきます。
dbtにはGUIベースのdbt cloudとCLIベースのdbt coreの2種類がありますが、基本的にdbt coreの前提で話をします。
想定しているdbtの使い方
本記事では、データサイエンティストがデータの内容を確認しつつ課題に対してどのようなアプローチができるかを検討する段階や、その検証を行うような分析のフェーズでdbtを利用する状況をぼんやりと念頭に置いています。
したがって、データに関する情報が曖昧であったり、そもそも何をしたいのかという部分が不明確な場合も含まれており、基本的にはかっちりと仕様を決めてテーブルを管理するためというよりは、dbtの最低限のルールだけ守りつつ、かなりライトに使うことを想定しています。
具体的には、SQL(やpython)でmodelを定義してテーブルを作成しつつ、その周辺のdocumentationやtestsの利用を考えています。
逆にいえば、複雑なmacroを組んで、依存を作りすぎない方が良いと思っています。プロジェクトが進んでシステム化する際にdbtを使わない可能性もあるので、なるべく疎結合にしておきたいですね。
分析の現場におけるdbtの恩恵
lineageがから自動作成できる
lineageはdocumentationの機能です。
画像のように、どのテーブルがどのテーブルの作成に必要なのかを示す関係図を自動生成してくれます。
データリネージの有用さは言わずもがなかもしれませんが、
- あるテーブルを修正したいがどの範囲のテーブルや集計結果に影響があるのか
- そもそもテーブルを修正するためにどのテーブルから見直せばいいのか
- 作ろうと思っているテーブルに近いものがすでにあるのか
など、様々なことが図から読み取れます。もちろん担当メンバーに確認すれば分かることですが、そのコミュニケーションがスキップできることが大切です。担当者がすでにプロジェクトにいない可能性もあります。属人化を駆逐していきましょう。
SQLを書けば自動的に生成されるという部分も重要です。
カラムの意味合いすら曖昧で探索的な進め方をしている状況ですと、どうしても一時的なテーブル・やむを得ず作った中間テーブルなどが乱立してしまいます。
そうなると、プロジェクト内で使われるテーブルの更新の頻度が高まっていいき、人手で管理している関連図は必ずどこかで更新されなくなります。自動で作成できるドキュメントは自動で作成しましょう。
テーブル定義書が自動生成される
同じくdocumentationの機能です。
テーブル定義書がsqlと同じリポジトリ上で管理される点がまずうれしいですね。
公式documentより
こちらはdescription
などをある程度人手でyamlを書かなければなりませんが、必要な作業でしょう。
少なくとも、何もせずカラム名とその型は表示してくれるので最低限のところまで自動で生成してくれます。
また、サードパーティーにはなりますが、yamlファイルへのカラム名などをある程度自動生成するpackageがあります。
単純なテストが簡単にできる
testsの機能です。
例えば、トランザクションデータなどを追加で受領するということは受託分析ではよくあります。
もちろん最初に「おかしなデータがないか」を確認しますが、複雑なドメイン知識などが不要な内容や、ルーティン化しているチェックは自動で行いたいですね。dbtはデフォルトで4つのテストを備えており、yamlに記述することで簡単に実行できます。
# https://docs.getdbt.com/docs/build/tests より
version: 2
models:
- name: orders
columns:
- name: order_id
tests:
- unique
- not_null
- name: status
tests:
- accepted_values:
values: ['placed', 'shipped', 'completed', 'returned']
- name: customer_id
tests:
- relationships:
to: ref('customers')
field: id
test | 内容 |
---|---|
unique |
カラムの値がユニークである |
not_null |
カラムの値にnullが含まれない |
accepted_values |
カラムの値にvalues で指定した値以外を持たない |
relationships |
to で指定したテーブルの filed カラムと同じである |
またsqlを追加で書く必要はありますが、独自のtestを作成することもでき、受領のごとのチェックのためだけでなく新しいメンバーにどのような観点でデータを見れば良いかを簡単に共有できます。
テーブル関係の複雑化を抑制
ここだけ若干抽象的な内容になりますが、dbtの枠組みでテーブルを作成することになるので、ある程度統一された構造を保ちつつ分析のテーブルが作成されるメリットも考えられます。
分かりやすいものですと、例えばDAGの構造を満たすテーブル関係になります。そもそも循環参照するような関係を作るなという話ではありますが、アドホックにデータを扱っていると何が起こるか分からないので、システム的に防げるのはうれしいですね。ちなみにdbtはコンパイルの段階で循環参照を検知してエラーを出してくれます。ありがたや。
また、dbtというベースの環境があることで、テーブルのレイヤをどうするかや、どの処理を何に任せるか(pandasやsqlなど) という基準が設けやすくなるかもしれません。半分願望が入っているかもしれませんが、少なくとも絶望的に散らかってしまうことはないでしょう。ある程度のデータ操作が統一されることで、分析からシステム化のフェーズになった時に、全てを書き直すということを防げるかもしれませんね。
分析の現場へ導入する上での障壁
ドキュメントを静的に取り出しにくい
メリットとしてご紹介したlineageとテーブル定義書のdocumentに関して、データサイエンティストだけが使う分には問題ではないのですが、プロジェクト外のリポジトリへのアクセス権がないメンバやcli操作に慣れていない方に共有するとなると若干取り回しが面倒です。
表示されているdocsが静的なページとして保存されていない関係で、現時点では簡単にエクスポートができないようです。
これはissueとしてもあがっていますね。
データソースとの連携が必要
データレイクやデータウェアハウス等にデータが登録されている前提で動作するツールのため、そういった基盤がない場合は構築するところからになるため、ハードルがあがるかもしれません。
軽量なデータをローカルだけで扱いたい場合は、ローカルでDBを立ち上げてseedsの機能を使う方法などが考えられるかもしれません。例えばDuckDBを使う方法はこちらの記事で紹介されています。
機械学習パイプラインとの組み合わせが悩ましい
これは私自身の知識不足なのかもしれませんが、dbtと機械学習パイプラインを組み合わせたときに、処理の切り分けをどのように設計にするかが難しいように感じられます。
例えばdbt上で作成した特徴量のテーブルを読み込み、予測を行い、結果を改めてテーブルに格納するという状況を考えると、outputのテーブルは若干dbtの枠組みからは外れる、もしくは新しいsourceテーブルとしての管理になってしまうため、テーブルの関係が複雑になってしまいます。
予測を行ってoutputを出したらおしまいであればいいのですが、往々にしてさらにそこからテーブルの変換を行っていくので、単純なテーブルの関係で収まらない可能性が高いでしょう。
結び
簡単ではありますが、社内の方々と議論していた内容をもとに、データサイエンティストがdbtを使う場合どのようなメリット/デメリットが考えられるかを紹介させていただきました。
ドキュメントの管理は重要ではあるものの可能な限り楽をしたいところですので、こういったツールを使いつつうまく自動化して、より分析などの本質的な作業に注力できるよう工夫していきたいです。
という月並みな感想で、本記事は締めくくらせていただきます(笑)
ここまで読んでいただきありがとうございました。残りのアドベントカレンダーもぜひお楽しみください。