dbtvault で BusinessVault
この記事は dbt Advent Calendar 2022 の12月2日の記事です!(ですが、公開したのは23日の夜です)
dbtvault?
dbtvault パッケージは、 dbt で使える Data Vault 構築用のパッケージです。
dbtvault によって提供されるマクロを使えば、 Data Vault モデルの手書きをする手間をかなり減らすことができます!
Business Vault vs Raw Vault
Data Vault には、 Business Vault と Raw Vault と呼ばれる2つのモデルのカテゴリがあります。
一般的に有名なのは Raw Vault で、単に Data Vault といった場合には Raw Vault を指す場合さえあります。
Raw Vault はステージングから直接構築される上流に近いモデル群です。
それに対して、 Business Vault はビジネス要件を反映したモデルであり、データマートのデータソースになるなど、下流に近い場所でモデリングされます。
Business Vault
Business Vault には下記の2つモデルがあり、どちらもビジネス要件を一部反映したものとなっています。
- PIT(Point In Time)
- Bridge
PIT
PITテーブルは、Hubが持つ複数のSatelliteをクエリーするのを楽にするために作るテーブルです。
Raw Vault の Hub と Satelite をジョインすることで、上流から来た元のテーブルの構造が作れます。
ただし、 Raw Vault は履歴を持つため単純にジョインしてしまっては複数行同士が結合され重複行を作ってしまいます。
多くの場合、ビジネス要件によって、特定の日のデータや、一定間隔ごと(毎週月曜)のデータが必要です。
したがって、 Raw Vault から元のテーブル構造を作る際には日付条件を合わせて指定し、たくさんのジョインが必要となります。
-- 従業員Hubを中心にSateliteをジョインしていく例
SELECT H.HUB_EMPLOYEE_KEY, H.EMPLOYEE_ID, S.FIRST_NAME, S.LAST_NAME,
S.HIRE_DATE, C.SALARY
FROM HUB_EMPLOYEE H
JOIN SAT_EMPLOYEE_NAME S
ON H. HUB_EMPLOYEE_KEY = S. HUB_EMPLOYEE_KEY
AND S.SAT_LOAD_DTS =
(SELECT (MAX(S2.SAT_LOAD_DTS)
FROM SAT_EMPLOYEE_NAME S2
WHERE H. HUB_EMPLOYEE_KEY = S2. HUB_EMPLOYEE_KEY
AND S2.SAT_LOAD_DTS <= '2022-12-01')
JOIN SAT_EMPLOYEE_COMPENSATION C
ON H. HUB_EMPLOYEE_KEY = C. HUB_EMPLOYEE_KEY
AND C.SAT_LOAD_DTS =
(SELECT (MAX(S3.SAT_LOAD_DTS)
FROM SAT_EMPLOYEE_COMPENSATION S3
WHERE H. HUB_EMPLOYEE_KEY = S3. HUB_EMPLOYEE_KEY
AND S3.SAT_LOAD_DTS <= '2022-12-01')
-- ・・・
-- 必要なSatelliteの数だけ、ジョインとサブクエリのセットが続く
-- ・・・
このように、元のテーブルを復元するためのジョインであっても、履歴テーブルという特性上、複雑なクエリを要してしまい、分析者のアジリティを下げてしまいます。
これを解決するのが、ここで紹介するPITです。
PITを用いた場合は上記のクエリは、下記のようになります。
-- 従業員Hubを中心にSateliteをジョインしていく例
SELECT H.HUB_EMPLOYEE_KEY, H.EMPLOYEE_ID, S.FIRST_NAME, S.LAST_NAME,
S.HIRE_DATE, C.SALARY
FROM HUB_EMPLOYEE H
JOIN SAT_EMPLOYEE_NAME S
ON H. HUB_EMPLOYEE_KEY = S. HUB_EMPLOYEE_KEY
JOIN SAT_EMPLOYEE_COMPENSATION C
ON H. HUB_EMPLOYEE_KEY = C. HUB_EMPLOYEE_KEY
JOIN EMPLOYEE_PIT P -- これがPIT
ON H. HUB_EMPLOYEE_KEY = P. HUB_EMPLOYEE_KEY
AND P.PIT_LOAD_DTS = '2022-12-01'
AND P.NAME_LOAD_DTS = S.SAT_LOAD_DTS
AND P.COMENSATION_LOAD_DTS = C.SAT_LOAD_DTS
どうでしょうか?PITをジョインするだけで、元のクエリにあった個別のサブクエリが不要になり、クエリの構造がシンプルに変わっています。
またシンプルになるだけではなく、データ量によっては無視できないレベルのパフォーマンス改善にもつながります。
PITマクロ
便利なPITですが、手書きのSQLで生成するのは非情に骨が折れます。
また、VIEWで表現したり、日次バッチで生成するなどの場合は、さらにSQLの難易度は上がっていきます。
これを dbtvault の pit マクロを使うことで、簡易に PIT を実現することができます。
{{ dbtvault.pit(source_model=source_model, src_pk=src_pk,
as_of_dates_table=as_of_dates_table,
satellites=satellites,
stage_tables=stage_tables,
src_ldts=src_ldts) }}
ぜひ PIT マクロを使って、複雑になりがちなデータマート構築を楽に進めてください。
参考:https://dbtvault.readthedocs.io/en/latest/tutorial/tut_point_in_time/
Bridge
Bridge は PIT 同様に、クエリを楽にするためのヘルパー的なテーブルです。
またクエリを楽にするだけではなく、明確にパフォーマンス改善も目的としています。
Bridge は Satellite のジョイン可能な列と利用したい列を持ったテーブル構造を持ちます。
複数の Link を介した、複数の Hub と Satellite のジョインは少し考えるだけで、複雑なSQLを想像できます。
例えば第3正規化されたテーブルのジョインは3テーブルで良い場合にも、 Data Vault であれば、8テーブルのジョインを必要とします。
また、単純にジョインするだけでは、 PIT でも説明したとおり、日付条件も必要となり、単純なジョインだけでなくサブクエリまで登場して、だんだん想像したくないくらい複雑なSQLが思い浮かんでしまいます。
Bridge にビジネス要件として必要な Satellite の列をすべてもたせることで、ジョインせずに必要なデータをキャッシュしているテーブルです。
データマートのデータソースとする場合でも、 Raw Vault とした場合、大量のジョインとサブクエリが発生するのに比べ、データマートが必要とする列をすべて持った Bridge からデータマートを生成すれば、一つもジョインやサブクエリが発生せず、明確にパフォーマンス向上が期待でき、 Snowflake など従量課金制のデータウェアハウスでは、Bridge の効果はコスト削減にまで及びます。
そのため、ビジネス要件が出てくる都度、 Bridge を検討すると良いでしょう。
Bridge マクロ
このようにとても有効な Bridge ですが、やはり手で生成するとなると困難なSQL実装を強いられます。
これが Bridge マクロであれば、本当にシンプルに記述できます。
{{ dbtvault.bridge(source_model=source_model, src_pk=src_pk,
src_ldts=src_ldts,
bridge_walk=bridge_walk,
as_of_dates_table=as_of_dates_table,
stage_tables_ldts=stage_tables_ldts) }}
PIT マクロ同様、 Bridge マクロも積極的に活用しましょう。
参考:https://dbtvault.readthedocs.io/en/latest/tutorial/tut_bridges/
終わりに
2022年は、 dbtvault が一気に定着したように感じます。
これは、対応データウェアハウスが、もともと Snowflake のみだったものが、2022年には、 BigQuery 、 SQLServer 、 PostgreSQL 、 Databricks と対応するDBが圧倒的に増えたからです。
ぜひご自分のデータ基盤でも、圧倒的生産性誇る dbtvault の導入を検討してみてはいかがでしょうか?
Snowlfake データクラウドのユーザ会 SnowVillage のメンバーで運営しています。 Publication参加方法はこちらをご参照ください。 zenn.dev/dataheroes/articles/db5da0959b4bdd
Discussion