🌊
"How we structure our dbt projects"を読む
概要
- dbt style guideを読んでいたら、このポストを参照していて、とても内容が濃かったので別でまとめました
- 同僚に読んでもらうために、僕なりに翻訳、噛み砕いたものなのとなっています
- 原文と若干ニュアンスが違うかもしれません、Single Source of Truthの精神でぜひ原文も読んでみてください
tenajimaの感想
- dbtのプロジェクトをどのように構築していくべきか学ぶ中で、データをどのように捉えるべきか(dimensionとfactなど)も同時に学べてすごく良かった
- 僕も型として「このパターンはこのようにプロジェクトを作っていく」というのを何個か持てるようになりたい
How we structure our dbt projects
前提としてここで示す方法は、dbtとしてはベストだと思うが、自分自身のプロジェクトにとって最適かどうかは自分で判断してね(より深くディスカッションして使ってね)って言ってる
Data transformation 101
- プロジェクトのデータは3つのチェックポイントで分けている
-
- ソース
- データソースに準拠した構造(例えばテーブルやカラム)をサードバーティーツールで読み込んだもの
-
- ステージングモデル
- データモデリングの最小単位
- 各モデルはソースデータテーブルと一対一の関係を持つ
- ソースデータテーブルと粒度は同じだが、カラムはリネーム、リキャストなど有用なものに整えられている状態にする
-
- マートモデル
- ビジネスプロセスやエンティティを表現するモデルで、ベースとなるデータソースから抽象化されている
- ここで注目すべきなのはソースとステージングモデルはデータソースが基点なのに対して、マートモデルはビジネスが基点であること
- dbtおすすめのプロジェクトではまずmodelsディレクトリをを以下のように構成することから始めるべき
├── dbt_project.yml
└── models
├── marts
└── staging
Staging raw data
- ステージング層の目的は生データを受け取り、データクレンジングを行うことだ
-
stg_
というプレフィックスを持つことは次のことを示す- データ基盤のルールに従ってフィールドをリネーム、リキャストしている
- タイムゾーンなどのデータ型が揃っている
- 空文字をnullに置き換えるなどの簡単なクレンジングが行われている
- 有用であればリストの展開(flattening)が行われている
- ユニークかつ非null値であるプライマリキーがある
- ステージングモデルにはコンテキストの追加のために、追加カラムを結合が可能で、ユニオンによる行の追加やフィルタによる削除、ナチュラルキーの重複排除やサロゲートキーのハッシュ結合もできる
- 複数のデータソースを扱うことが多いので、ステージングディレクトリでは、ソースごとに1つのディレクトリを作成する
├── dbt_project.yml
└── models
├── marts
└── staging
├── braintree
└── stripe
- それぞれのstagingディレクトリは最低限次のものを含む
- 分析に有用な各オブジェクトに1つのステージングモデル
-
stg_<source>__<object>
というファイル名にする
-
- 1つの
src_<source>.yml
ファイル- sourceの定義、テスト、ドキュメントを記述する
- 1つの
stg_<source>.yml
ファイル- 同じディレクトリのモデルのテストとドキュメントを書く
- 分析に有用な各オブジェクトに1つのステージングモデル
├── dbt_project.yml
└── models
├── marts
└── staging
└── braintree
├── src_braintree.yml
├── stg_braintree.yml
├── stg_braintree__customers.sql
└── stg_braintree__payments.sql
- ymlファイルを1つにまとめたいという声も合理的だが、ymlが肥大化してきたらこの方法をお勧めする
- ephemeral materializationをよく使うようになってきたらbaseディレクトリを使って作る
Describing a business through marts
- martsはビジネスエンティティやビジネスロジックを含んだモデルを置くところ
- ビジネスの単位でディレクトリを切るのが良い
- マーケ、経理、プロダクト
├── dbt_project.yml
└── models
├── marts
| ├── core
| ├── finance
| ├── marketing
| └── product
└── staging
- ここではファクトモデルとディメンジョンモデルを構築し、そのモデルが依存するソースデータから抽象化することが目標である
-
fct_<verb>
- 行数が多くて列数が少ないデータ
- 実世界で発生した、あるいは発生しているプロセス
- セッション、トランザクション、オーダー、などイミュータブルなイベントストリーム
-
dim_<noun>
- 行数が少なくて列数が多いデータ
- 各レコードは人、場所、ものなどを表す
- (人の属性情報など)劇的に変化するなどはないが、ミュータブルである
-
- ステージングモデルの作業がクリーニングなどの前処理に限られているのに対し、ファクトテーブルはディメンジョンの選択(および削除)、日付の特定、ビジネスロジックの実行といっデータ変換を行う部分である
- このレイヤーのモデリングはステージングモデルの作成よりもかなり複雑で、組織の分析ニーズに適合した形になる
- ここでは便利なパターンをいくつか紹介する
- パフォーマンスを上げるために
fct_
とdim_
モデルをテーブルとして作る。基本的にはテーブルとして作るが、パフォーマンス懸念があるときのみインクリメンタルで作る - ファクトモデル、またはディメンジョンモデルを作る前に必要な途中での変換は
marts/<mart>/intermadiate
ディレクトリに配置する。<useful_name>__<transformation_in_past_tense>.sql
という名前で格納する。二重アンダースコアが使われていることからこれらは中間モデルであることを示すようにする。 - モデルは同一ディレクトリの
<dir_name>.yml
ファイルにてテストを行うようにする
├── dbt_project.yml └── models ├── marts │ ├── core │ │ ├── core.md │ │ ├── core.yml │ │ ├── dim_customers.sql │ │ ├── fct_orders.sql │ │ └── intermediate │ │ ├── customer_orders__grouped.sql │ │ ├── customer_payments__grouped.sql │ │ ├── intermediate.yml │ │ └── order_payments__joined.sql │ ├── finance │ ├── marketing │ └── product └── staging
- DAGで表すとこのように表される
- パフォーマンスを上げるために
Accessories to data
ロバストなdbtプロジェクトで見かけるSQLファイルには、ステージングやマートに加えて次のようなモデルディレクトリがしばしば見られる
-
utils
-
all_days
テーブル、あらゆるところで役に立つ
-
-
lookups
- zipcodeと国を紐づけるなどのマッピングテーブル
- これらはcsvと
dbt seed
を使って用意するのが良い - これはいろんなところで参照するだけでなく、BIツールで使うこともある
-
admin
- 監査ログ、DWHの運用、メンテナンス情報、プロジェクトを進めるために実行した雑多なDDLのインクリメント記録など
-
metrics
- ファクトテーブルから取得した測定値から正確に定義されたもの
Final thoughts
- この記事ではdbtによってDAGを構築することを説明した
- それはソースモデルからマートモデルまで左から右に処理をすることを説明した
- しかし、現実ではしばしば右から左へモデルを考えることが多い
- ダッシュボードのアイデアや、作りたいレポートから考え始めて、ダッシュボードをワークさせるために必要なマートモデルの構造をホワイトボードに書き出す
- 実際にSQLを書き始める前に、同じホワイトボードにデータソースまで遡るように処理を書き出す
- 何度かモデリングを繰り返すうちに、DAGを左から右へどう構築していけば良いのか直感的にわかるようになってくる
- 目的地を考えてからモデリングの旅に出るようになってくるのだ
Discussion