データ分析基盤グループでデータエンジニアをしている平川です。
近年注目されてきているDataVaultに関して、全3回(予定)で記事を書かせていただく予定です。
第1回の記事では、DataVaultとは何なのか?どんな特徴があるのかを書いていきます。
参考までに、1~3回の内容を紹介しておきます。(内容は変わる可能性が大いにありますのでお許しください🙇♂️)
第1回: DataVaultってなに?どんな特徴があるの? ← 今回はここ
第2回: dbtvaultを使って実際にDataVaultモデリングでテーブルを作ってみた
第3回: BusinessVaultの使い所や特徴的なSatelliteの利用におけるハマったところや良いところ
これまでのデータモデリング手法
分析基盤構築において、データウェアハウス(DWH)層で行うデータモデリングは、アプリケーション開発のデータモデリングとは目的が異なります。 アプリケーション開発におけるデータモデリングの主な目的はシステムを円滑に動かすことです。 一方、DWH層でのデータモデリングはデータ分析のしやすさやデータの履歴化が目的になります。 両者の目的は異なるため、必要となるデータモデリングにも違いが現れます。
次に、これまでDWH層で使われてきたデータモデリングについて紹介します。
主要なデータモデリング手法には大きく2つあり、William Inmon氏が提唱した第3正規形(3NF)によるモデリングとRalph Kimball氏が提唱したディメンショナルモデリングがあります。
今回はこれらのデータモデリングが主テーマではないですが、それぞれの特徴や課題を簡単にまとめておきます。
3NF
3NFによるモデリングは、アプリケーション開発でも使われている3NFと同じ意味です。3NFはテーブルの数が膨大なDWHの実装で使われることが多いです。 3NFの目的は、各テーブルの関係や情報を可能な限り詳細に保持することにあります。データソースであるアプリケーション全体のデータモデルをDWHに構築します。
3NFの問題点としては、作成するテーブルの数が膨大であることで、初期構築に多くの労力と期間が必要となることと新規パラメータの追加などへの柔軟性が低いことです。そのためユーザからの新たなパラメータの追加など柔軟性が高いとは言えません。
ディメンショナルモデリング
ディメンショナルモデリングは、データソース(アプリケーション側のデータや別システムのデータ)をディメンションテーブルとファクトテーブルに分割して作成します。 ディメンションテーブルには、商品名などの属性情報を格納し、ファクトテーブルには売上などの数値情報が格納されます。
ディメンショナルモデリングはアプリケーション開発におけるデータモデリングとは構造が大きく異なり、データ分析に特化した構造になります。
ディメンショナルモデリング手法をもとに構築されたテーブルは、データがディメンショナルとファクトで分割されていることで、データの理解がしやすくなります。
さらに、分析する際に実行するクエリも単純になります。一方でデータの変更対応には多くの時間やコストがかかります。
DWH層だけでなく、データマートの層においてもディメンショナルモデルが使われることが多いです。
これまで使用されてきた2つのデータモデリング手法には初期構築やデータの追加に多くの時間が取られるという課題があります。 データを使って意思決定を行いたいユーザは、分析基盤に変化するビジネスロジックに対する迅速な対応を期待します。 迅速で柔軟な対応のためには、リリースサイクルが短い方が利点があります。 柔軟性に欠けるという課題に対して、近年ではDataVaultと呼ばれるモデリング手法が注目されてきています。
DataVaultとは何か?
DataVaultデータモデリングは、2000年頃にDan Linstedt氏が提唱したデータモデリング手法で現在では、進化を遂げてDataVault2.0(DV2.0)と呼ばれています。
DV2.0に基づいて作られたテーブルは、キー情報・テーブル間の関係情報・属性情報をそれぞれ格納する3つのテーブルに分割されます。 データを3つのテーブルに分離したことで、ビジネスロジックの変更に伴うデータの追加のような変化に対する柔軟さと俊敏さを手にしています。テーブルには一部の例外を除きデータをインサートするだけなので、データを履歴化して持つことができます。 さらに、特定の日付のデータを取得することが可能なことから監査の面でもメリットがあります。
データを分離しているという点ではディメンショナルモデリングと似ている部分もありますが、DV2.0では、テーブル間の関係情報も別テーブルで管理している点が、ディメンショナルモデリングとは異なっています。
DV2.0に基づいて作成される特徴的な3つのテーブルを紹介していきます。
Hub
Hubテーブルはビジネスにおける中心となる実体・存在(エンティティ)を表現します。
Hubテーブルにはビジネスキーが格納されています。ビジネスキーは、エンティティをユニークにするキーのことを指します。ナチュラルキーとも呼ばれます。Hubテーブルに含まれるビジネスキーはビジネスの中心となるものなので、不変ないしは、ほぼ変化しないものが選ばれます。
テーブルを構成する要素は、ビジネスキーとそのhash key、さらにデータをロードした日付(or 日時)とどのデータソースからデータが来たかを示すカラムで構成されます。どのデータソースからデータが来ているかというカラムをRecord Sourceと呼び、元テーブルの名前やシステム自体の名前を格納します。
dbtvaultというdbtのパッケージのドキュメントでは、Record Sourceには元テーブルの名前を格納しています。
最後に簡単なテーブル構造の例を挙げておきます。
column | type | example |
---|---|---|
product_pk | binary | 27634ff8002b12e75d98e07ccd005d18 |
product_name | varchar | Water |
loaded_on | date | 2022-12-01 |
record_source | varchar | products |
Link
Linkテーブルの役割は全てのテーブル間の関係を表現することです。
テーブル構成は関係する2つのテーブルのhash keyと2つのテーブルのビジネスキーをconcatしてhash化したキーとHubテーブル同様にロードした日付とRecord Sourceで構成されます。
テーブルの構成は以下のようになります。
column | type | example |
---|---|---|
order_product_pk | binary | 6fd0207c2d9ce3dcaddf870e96721a4b |
order_pk | binary | c4ca4238a0b923820dcc509a6f75849b |
product_pk | binary | 27634ff8002b12e75d98e07ccd005d18 |
loaded_on | date | 2022-12-01 |
record_source | varchar | orders |
Satellite
Satelliteテーブルには、対象のエンティティの全ての属性情報が格納されます。
具体的には、商品というエンティティがあれば、値段や製造日のようなデータが格納されます。Satelliteテーブルはビジネスキーのhash keyとロードされた日付(日時)を主キーとします。
テーブルの構成は以下のようになります。
column | type | example |
---|---|---|
product_pk | binary | 27634ff8002b12e75d98e07ccd005d18 |
hashdiff | binary | 1e6e0a04d20f50967c64dac2d639a577 |
price | number | 100 |
loaded_on | date | 2022-12-01 |
record_source | varchar | products |
Satelliteテーブルの特徴的なカラムは上記図にもあるhashdiffです。hashdiffカラムは属性情報を全てconcatしhash化した値です。 hashdiffの生成には全ての属性情報を使うため、属性情報に変更があった場合、hashdiffの値は変化します。 全ての属性情報のカラムを見るのではなく、hashdiffカラムだけを見ればよいため変更の検知が容易になります。
上図で示した例は属性情報のカラムが一つだけですが、属性情報が大量にあるエンティティを扱う可能性もあります。属性情報が大量にある場合、データの種類や変更頻度などでSatelliteテーブルを分割することも可能です。
Hub/Link/Satelliteテーブルの関係性を図にすると以下のようになります。
モデリングにおける注意点
DV2.0モデリングを進めていく際は、ビジネスの中心となるエンティティを最初に定義する必要があります。
なので今回紹介したHub > Link > Satelliteの順番でモデリングしていくことが推奨されます。
また、Hub/Link/Satelliteの3つのテーブルをまとめてRawVaultとも呼びます。
今回紹介したテーブル例ですとソースシステムのテーブルをただ3つのテーブルに分割しているだけですが、モデリングする際にソースシステムのテーブルのカラムを単純にHub/Link/Satelliteに分割することは良い手段とは言えません。
DataVaultを提唱したDan Linstedt氏曰く(元のブログポストはすでに消えてしまっているようです...)
"Data vault modeling was, is, and always will be ABOUT THE BUSINESS. And if the Data Vault you have in place today is not currently about the business, then unfortunately you've hired the wrong people, and those people need to go back to school and relearn what Data Vault really means. Or you've build the wrong solution, and you need to fix it-immediately."
と言っています。 ざっくりいうと、DataVaultモデリングは常にビジネスに関わるものでなければいけないということです。 ビジネスロジックなどを考えずにソースシステムのデータをそのままDataVault風に分割するのは適当とは言えません。
ここまで、DataVaultを構成するテーブルについて簡単に紹介させていただきました。DataVaultのメリットの片鱗は少し見えてきたかもしれませんが、次の章でDataVaultの優れている点をまとめていきます。
さらに、構築する上で課題となる点も紹介していきます
DataVaultの優れている点と課題
DataVaultモデリングの優れている点はいくつかあると思いますが、個人的に他のモデリング手法よりも優れていると思われる点を3点ほど紹介させていただきます。
DataVaultの優れている点
監査能力の高さ
DataVaultモデリングで作成されたテーブルにはインサートしかしません。(一部例外はありますが...)
よって、過去の指定の時点のデータの状態を保持することが可能になります。インサートしかしないため、データの履歴化も可能になっています。
取得するデータが増える場合のような変更に対する柔軟性の高さ
DV2.0モデリングに基づいて作られたテーブルはHub/Link/Satelliteに分割されています。
新規に追加するデータが、既に作成しているHubの属性情報であれば、Satelliteテーブルを作成するだけでデータ追加の対応が完了します。既にあるテーブル自体を拡張したりする場合と比べると考慮しないといけない点が減っています。
短いリリースサイクルでDWHを更新することの容易さ
テーブルの設計方針が明確なため、新しいデータを取り込むことが他のモデリング手法と比べると容易なため変更へのコストが低くなります。そのため短い開発サイクルでリリースをすることが可能になります。そのため、ユーザー(データを使って意思決定をしたい人たち)が望んでいるビジネスロジックの変更に対する迅速な対応が実現できます。
紹介した以外にも、まだまだDV2.0の優れている点はあると思います。
一方で、残念ながらDV2.0にも課題があります。
DataVaultの課題点
クエリがJOINだらけになる
1つのエンティティから最低でも3つのテーブルが作成されるため、3NFやディメンショナルモデルと比べてテーブルが多くなります。
2つのエンティティ、例えば注文と商品というエンティティがあるとすると、商品情報と注文情報の両方を取得するには、以下のようなSQLを書く必要があります。
select order_name, product_name, order_created_at, price from hub_orders ho inner join link_order_products lop on ho.order_hk = lop.order_hk inner join hub_products hp on hp.product_hk = lop.product_hk inner join sat_orders so on so.order_hk = ho.order_hk inner join sat_products sp on hp.product_hk = sp.product_hk where sat_orders.loaded_at = ( select max(loaded_at) from sat_orders so2 where so.order_hk = so2.order_hk ) and sat_products.loaded_at = ( select max(loaded_at) from sat_products sp2 where sp.product_hk = sp.product_hk )
上記のようなJOINだらけのクエリが生成されてしまい、可読性が高くありません。 なので、今回紹介したHub/Link/Satelliteテーブルだけを使って分析するのはクエリ自体は単純ですが、記述がかなり大変になります。
JOINが多くなってしまう課題への対処方法の一つはBridgeテーブルを作成することです。BridgeテーブルはHub/Link/Satelliteの各要素を統合してまとめたテーブルになります。 つまり、分析する際に毎回実行するようなデータの統合処理は先にやってしまおうという考え方です。
また、1つのHubに複数のSatelliteが付随している際に、それぞれのSatelliteテーブルの任意の時点のデータを抽出するというクエリも複雑になります。 この課題に対しては、PIT(Point In Time)テーブルの作成をすることが有効な手段と言えます。
データの統合や特定の期間のデータだけを取り出すような、ビジネスロジックの追加やデータを解釈する必要がある場合は、RawVaultとは別のテーブルを作成すると問題を解消できます。 Bridge TableやPIT TableのようなBusiness Vaultについての紹介は第3回でさせていただければと思います。
初期構築時に「正しく」Hubを設計することが簡単ではない
元のデータソースのテーブルをHub/Link/Satelliteに分けるだけで、見た目的にはRawVaultは構築できます。 DV2.0はビジネスに関するものであるという考え方からすると、単純にソーステーブルのデータを3つのテーブルに分割することは、必ずしも良い手段とは言えません。 DV2.0は、カラムの追加や取り込むシステムに対する柔軟性は高いですが、柔軟性が高いと言える状態にするためには、設計原理に基づいてRawVaultを設計する必要があります。
一見簡単に構築できそうですが、ビジネス理解やドメイン知識の理解がないとダメで、要求される知識が多く、初期構築が難しくなると思います。 設計・構築の難しさはモブプログラミングのような形式のモブモデリングである程度対処できるかもしれません。
まとめ/次回予告
本記事では、DataVaultモデリングに関する投稿の第1回として、モデリングの特徴や構築されるテーブルについて簡単に紹介させていただきました。
今回紹介したHub/Link/Satelliteがどんなカラムを持っているか最後に振り返っておきます。
Hub
- ビジネスキー/ナチュラルキーのhash化した値
- ビジネスキー/ナチュラルキー
- ロードした日時/日付
- 元ソースの名称
Link
- Hubのビジネスキー/ナチュラルキーをconcatしてhash化した値
- Hubのhash key その1
- Hubのhash key その2
- ロードした日時/日付
- 元ソースの名称
Satellite
- ビジネスキー/ナチュラルキーのhash化した値
- 属性情報を全てconcatしてhash化した値
- 属性情報(価格や登録日など)
- ロードした日時/日付
- 元ソースの名称
次回の記事では、これら3つのテーブルをdbtvaultというdbtのパッケージを使って構築する方法や実際に構築する際に困った点などについて紹介できたらと思います。
最後に、本記事を書くにあたり様々な書籍・ブログポスト・登壇資料などを参考にさせていただきました。より詳しい内容を知りたいという方はぜひ参考資料を見てみてください。
参考資料
- Building a Scalable Data Warehouse with Data Vault 2.0
- The Elephant in the Fridge: Guided Steps to Data Vault Success through Building Business-Centered Models
- The Data Vault Guru: a pragmatic guide on building a data vault
- Data Vault as a Modeling Concept for the Data Warehouse
- dbtvault入門
- DataVault2.0をご紹介