DatabricksレイクハウスにおけるData Vaultのベストプラクティスと実装

[What’s a Data Vault Model and How to Implement It on the Databricks Lakehouse Platform \- The Databricks Blog](https://www.databricks.com/blog/data-vault-best-practice-implementation-lakehouse)の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

以前の記事、[DatabricksレイクハウスプラットフォームにおけるData Vault実装の規範的ガイド](https://qiita.com/taka_yayoi/items/7d75c3d1a35bee719582)では、Data Vaultのコアコンセプトを説明し、Databricksでの活用ガイドを提供しました。我々には、レイクハウスでのData Vaultのサンプルや容易な実装を探している多くのお客様がいらっしゃいます。

本記事では、DatabricksレイクハウスプラットフォームにおけるData Vaultの実装方法にディープダイブし、[Delta Live Tables](https://www.databricks.com/jp/product/delta-live-tables)を用いたリアルタイムでのEDW Data Vaultモデルのロードのライブのサンプルを提供します。

この記事でカバーするハイレベルのトピックは以下の通りです:

1. なぜData Vaultなのか
2. レイクハウスにおけるData Vault
3. DatabricksレイクハウスにおけるData Vaultモデルの実装
4. まとめ

# 1. なぜData Vaultなのか

[Data Vault](https://en.wikipedia.org/wiki/Data_vault_modeling)の主要なゴールは、現代世界においてスケーラブルでモダンなデータウェアハウスを構築することです。コアにおいては、ビジネス世界をモデリングするためにハブ、サテライト、リンクを活用し、環境変化に対する回復性を持つ安定(ハブ)しつつも柔軟性(サテライト)のあるデータモデルとアーキテクチャを実現します。ハブには、コアのビジネスが変化しない限り変化しないビジネスキーが含まれ、Data Vaultモデルのスケルトンを構成しますが、サテライトには容易に作成、拡張できるハブのコンテキスト上の属性が含まれます。

設計上の3つのキーとなる利点を持つData Vaultのハイレベルのデザインに関しては以下をご覧ください:

1. 以下でわかるように、顧客、製品、注文のハブやサテライトは並列でロードすることができ、モデルのテーブル間の依存関係が少ないので、企業データウェアハウスの効率的な並列ロードを実現します。
1. テーブルにはインサートのみであり、ソースのメタデータを保持することが推奨されるので、生のVaultで単一のバージョンのファクトを保持します。
1. モデルに新たなハブやサテライトを容易に追加できるので、データ資産デリバリーの市場投入を高速にします。

![](https://cms.databricks.com/sites/default/files/inline-images/db-398-blog-img-1.png)
*Data Vaultモデルのコアコンポーネント*

# 2. レイクハウスにおけるData Vault

[Databricksレイクハウスプラットフォーム](https://www.databricks.com/jp/product/data-lakehouse)は、非常にうまくData Vaultモデルをサポートしており、レイクハウスにおけるData Vaultモデルのハイレベルなアーキテクチャについては以下をご覧ください。堅牢でスケーラブルな[Delta Lake](https://docs.databricks.com/delta/index.html)ストレージフォーマットによって、変更されていないデータが格納される生のVault、必要に応じてビジネスルールや変換処理が適用されるビジネスVaultの構築が可能となります。両方とも上述のデザインにアラインするので、Data Vaultモデルのメリットを享受することができます。
![](https://cms.databricks.com/sites/default/files/inline-images/db-398-blog-img-2.png)
*レイクハウスにおけるData Vaultモデル*

# 3. DatabricksレイクハウスにおけるData Vaultモデルの実装

以前のセクションのデザインによって、ハブ、サテライト、リンクテーブルのロードはわかりやすいものとなります。例えば、顧客と製品ハブテーブルは、両方とも自分だけのビジネスキーを持っているのでロード可能であるように、それぞれが依存していないことで並列にすべてのETLロードを行うことができます。`customer_product_link`テーブル、顧客サテライト、製品サテライトも、ソースから必要なすべての属性を取得しているので並列でロードすることができます。

## 全体的なデータフロー

以下の[Delta Live Table](https://www.databricks.com/jp/product/delta-live-tables)パイプラインにあるハイレベルのデータフローをご覧ください。我々の例では、意思決定支援ベンチマークでよく用いられるTPCHデータを使用しています。最初にブロンズレイヤーにデータがロードされ、Deltaフォーマットで格納され、これらはオブジェクトごと(顧客や注文のハブやサテライトなど)の生のVaultに登録するために使用されます。ビジネスVaultは、生のVaultのオブジェクト上に構築され、レポートや分析での活用のためにデータマートオブジェクト(dim_customer, dim_orders, fact_customer_orderなど)が作成されます。
![](https://cms.databricks.com/sites/default/files/inline-images/db-398-blog-img-3.jpg)

## 生のVault

生のVaultは生のデータを格納し、単一バージョンの真実を維持するハブ、サテライト、リンクテーブルを格納します。以下でわかるように、`raw_customer`をベースとしてビュー`raw_customer_vw`を作成し、必要に応じて存在確認や比較を行うためのカラムのハッシュを作成するためにハッシュ関数`sha1(UPPER(TRIM(c_custkey)))`を使用します。

```sql
-- create raw customer view and add hash columns for checking existence or comparison 
CREATE  STREAMING LIVE VIEW raw_customer_vw
COMMENT "RAW Customer Data View"
AS  SELECT
        sha1(UPPER(TRIM(c_custkey))) as sha1_hub_custkey,
        sha1(concat(UPPER(TRIM(c_name)),UPPER(TRIM(c_address)),UPPER(TRIM(c_phone)),UPPER(TRIM(c_mktsegment)))) as hash_diff,
        current_timestamp as load_ts,
        "Customer Source" as source,
        c_custkey,
        c_name,
        c_address,
        c_nationkey,
        c_phone,
        c_acctbal,
        c_mktsegment,
        c_comment
    FROM STREAM(LIVE.raw_customer)
```

生の顧客ビューが作成されたら、以下のコードサンプルを用いて顧客のハブとサテライトをそれぞれ作成します。Delta Live Tablesでは、`CONSTRAINT valid_sha1_hub_custkey EXPECT (sha1_hub_custkey IS NOT NULL) ON VIOLATION DROP ROW`のような[データ品質のエクスペクテーション](https://docs.databricks.com/workflows/delta-live-tables/delta-live-tables-cookbook.html#make-expectations-portable-and-reusable)を簡単にセットアップすることができ、エクスペクテーションによって定義されたデータ品質問題をパイプラインがどのようにハンドリングするのかを定義するために活用することができます。ここでは、適正なビジネスキーを持たないすべての行を削除します。

```sql
-- create hub customer table from the raw customer view
CREATE OR REFRESH STREAMING LIVE TABLE hub_customer(
  sha1_hub_custkey        STRING     NOT NULL,
  c_custkey               BIGINT     NOT NULL,
  load_ts                 TIMESTAMP,
  source                  STRING
  CONSTRAINT valid_sha1_hub_custkey EXPECT (sha1_hub_custkey IS NOT NULL) ON VIOLATION DROP ROW,
  CONSTRAINT valid_custkey EXPECT (c_custkey IS NOT NULL) ON VIOLATION DROP ROW
)
COMMENT " HUb CUSTOMER TABLE"
AS SELECT
      sha1_hub_custkey,
      c_custkey,
      load_ts,
      source
   FROM
      STREAM(live.raw_customer_vw)
```

```sql
-- create satellite customer table from raw customer view 
CREATE OR REFRESH STREAMING LIVE TABLE sat_customer(
  sha1_hub_custkey        STRING    NOT NULL,
  c_name                  STRING,
  c_address               STRING,
  c_nationkey             BIGINT,
  c_phone                 STRING,
  c_acctbal               DECIMAL(18,2),
  c_mktsegment            STRING,
  hash_diff               STRING    NOT NULL,
  load_ts                 TIMESTAMP,
  source                  STRING    NOT NULL
  CONSTRAINT valid_sha1_hub_custkey EXPECT (sha1_hub_custkey IS NOT NULL) ON VIOLATION DROP ROW
)
COMMENT " SAT CUSTOMER TABLE"
AS SELECT
      sha1_hub_custkey,
      c_name,
      c_address,
      c_nationkey,
      c_phone,
      c_acctbal,
      c_mktsegment,
      hash_diff,
      load_ts,
      source
   FROM
      STREAM(live.raw_customer_vw)
```

ほかのオブジェクトのハブとサテライトは同じような方法でロードされます。リンクテーブルに関して、`raw_orders_vw`をベースとして`lnk_customer_orders`を作成する例を示します。

```sql
-- create customer orders table from the raw orders view
CREATE OR REFRESH STREAMING LIVE TABLE lnk_customer_orders
(
  sha1_lnk_customer_order_key     STRING     NOT NULL ,  
  sha1_hub_orderkey               STRING ,
  sha1_hub_custkey                STRING ,
  load_ts                         TIMESTAMP  NOT NULL,
  source                          STRING     NOT NULL 
)
COMMENT " LNK CUSTOMER ORDERS TABLE "
AS SELECT
      sha1_lnk_customer_order_key,
      sha1_hub_orderkey,
      sha1_hub_custkey,
      load_ts,
      source
   FROM
       STREAM(live.raw_orders_vw)
```

## ビジネスVault

生のVaultでハブ、サテライト、リンクが作成されたら、それらをベースとしてビジネスVaultオブジェクトを作成できるようになります。これは、後段のステージで容易に利用できるように、データオブジェクトに追加のビジネスルールや変換ルールを適用するというものです。以下に、ビジネスVaultにおける注文オブジェクトの追加情報として`order_priority_tier`が追加される`sat_orders_bv`の構築例を示します。

```sql
-- create satellite order table in business vault from the satellite orders table in raw vault 
CREATE OR REFRESH LIVE TABLE sat_orders_bv
(
  sha1_hub_orderkey         STRING     NOT NULL ,  
  o_orderstatus             STRING ,
  o_totalprice              decimal(18,2) ,
  o_orderdate               DATE,
  o_orderpriority           STRING,
  o_clerk                   STRING,
  o_shippriority            INT,
  order_priority_tier       STRING,
  source                    STRING    NOT NULL
  
)
COMMENT " SAT Order Business Vault TABLE "
AS SELECT
          sha1_hub_orderkey     AS sha1_hub_orderkey,
          o_orderstatus         AS o_orderstatus,
		  o_totalprice          AS o_totalprice,
          o_orderdate           AS o_orderdate,
          o_orderpriority       AS o_orderpriority,
		  o_clerk               AS o_clerk,
          o_shippriority        AS o_shippriority,
		  CASE WHEN o_orderpriority IN ('2-HIGH', '1-URGENT') AND o_totalprice >= 225000 THEN 'Tier-1'
               WHEN o_orderpriority IN ('3-MEDIUM', '2-HIGH', '1-URGENT') AND o_totalprice BETWEEN 120000 AND 225000 THEN 'Tier-2'   
			   ELSE 'Tier-3'
		  END order_priority_tier,
          source
   FROM
       live.sat_orders
```

## データマート

最後に、後段のレイヤーでの利用を容易にするためのData VaultのPoint-in-Timeビューとデータマートにcustomerをロードします。ここでのメインのフォーカスは、使いやすさと読み込み性能の改善です。多くのシンプルなテーブルにおいては、ハブやサテライトの上にビューを作成するだけで十分ですが、最終レイヤーにおけるディメンショナルモデルのような適切なスタースキーマをロードすることも可能です。以下に、ビュー`dim_customer`として顧客のディメンションを作成し、クエリーをシンプルにするために、このビューを他の人が活用できるようにする例を示します。

```sql
-- create customer dimension as view in data mart from the hub and satellite customer table, ref nation and ref region table
CREATE LIVE VIEW dim_customer
       AS
       SELECT 
             sat.sha1_hub_custkey      AS dim_customer_key,
	         sat.source                AS source,                  
	         sat.c_name                AS c_name ,             
	         sat.c_address             AS c_address ,             
	         sat.c_phone               AS c_phone ,              
	         sat.c_acctbal             AS c_acctbal,             
	         sat.c_mktsegment          AS c_mktsegment,                          
	         sat.c_nationkey           AS c_nationkey,  
             sat.load_ts               AS c_effective_ts,
	         -- derived 
	         nation.n_name             AS nation_name,
	         region.r_name             AS region_name
	     FROM LIVE.hub_customer hub
         INNER JOIN LIVE.sat_customer sat
           ON hub.sha1_hub_custkey = sat.sha1_hub_custkey
	     LEFT OUTER JOIN LIVE.ref_nation nation
	       ON (sat.c_nationkey = nation.n_nationkey)
	     LEFT OUTER JOIN LIVE.ref_region region
	       ON (nation.n_regionkey = region.r_regionkey)
```

Data Vaultにおけるよくある問題の一つは、特に多くのテーブルの属性を必要とする複雑なクエリーやファクトが必要な際に、多すぎるjoinを行う結果になってしまうことです。Databricksにおける推奨は、毎回再構築する必要がないようにテーブルを事前にjoinし、必要に応じて計算したメトリクスを保存するというものです。複数のjoinをベースとしたファクトテーブル`fact_customer_order`を作成し、ビジネスユーザーが繰り返すクエリーで使えるようにテーブルに格納する例を以下に示します。

```sql
-- create fact customer order table in data mart from the lnk_customer_orders, dim_order, dim_customer, ref_nation and ref_region
CREATE OR REFRESH LIVE TABLE fact_customer_order
       AS
       SELECT 
           dim_customer.dim_customer_key,
           dim_orders.dim_order_key,
           nation.n_nationkey     AS dim_nation_key,
           region.r_regionkey     AS dim_region_key,
           dim_orders.o_totalprice AS total_price,
           dim_orders.o_orderdate  AS order_date
       FROM LIVE.lnk_customer_orders lnk
       INNER JOIN LIVE.dim_orders dim_orders
           ON lnk.sha1_hub_orderkey = dim_orders.dim_order_key
       INNER JOIN LIVE.dim_customer dim_customer
           ON lnk.sha1_hub_custkey = dim_customer.dim_customer_key
	   LEFT OUTER JOIN LIVE.ref_nation nation
           ON dim_customer.c_nationkey = nation.n_nationkey
       LEFT OUTER JOIN LIVE.ref_region region
           ON nation.n_regionkey = region.r_regionkey
```

## Delta Live Tableパイプラインのセットアップ

上述したすべてのコードは[こちら](https://github.com/dbsys21/databricks-lakehouse/tree/main/lakehouse-buildout/data-vault)にあります。お客様はDelta Live Tablesを用いて全体のデータフローを容易にオーケストレーションすることができ、どのように自分の環境でパイプラインをセットアップしたのかの設定は以下の通りであり、必要であれば、ご自身のワークフローでDelta Live Tableパイプラインをセットアップするのかの詳細については、[DLTの設定](https://docs.databricks.com/delta-live-tables/settings.html#settings)をご覧下さい。

```json
{
    "id": "6835c6ad-42a2-498d-9037-25c9d990b380",
    "clusters": [
        {
            "label": "default",
            "autoscale": {
                "min_workers": 1,
                "max_workers": 5,
                "mode": "ENHANCED"
            }
        }
    ],
    "development": true,
    "continuous": false,
    "channel": "CURRENT",
    "edition": "ADVANCED",
    "photon": false,
    "libraries": [
        {
            "notebook": {
                "path": "/Repos/prod/databricks-lakehouse/lakehouse-buildout/data-vault/TPC-DLT-Data-Vault-2.0"
            }
        }
    ],
    "name": "DLT Data Vault",
    "storage": "dbfs:/pipelines/6835c6ad-42a2-498d-9037-25c9d990b380",
    "configuration": {
        "pipelines.enzyme.mode": "advanced",
        "pipelines.enzyme.enabled": "true"
    },
    "target": "l
```

# 4. まとめ

この記事では、Data Vaultのコアのコンセプトと、[Delta Live Tables](https://www.databricks.com/jp/product/delta-live-tables)を用いてどのように実装するのかを学びました。[Databricksレイクハウスプラットフォーム](https://www.databricks.com/jp/product/data-lakehouse)は高信頼、効率的、スケーラブルな方法で様々なモデリング手法をサポートしますが、我々のサーバレスデータウェアハウスである[Databricks SQL](https://www.databricks.com/jp/product/databricks-sql)によって、レイクハウス上ですべてのBI、SQLアプリケーションを実行することができます。上述した例の完全なワークフローに関しては、[こちらのサンプル](https://github.com/dbsys21/databricks-lakehouse/tree/main/lakehouse-buildout/data-vault)をご覧ください。

関連記事もチェックしてみてください:

- [Delta Lakeを用いてDatabricksでスタースキーマを実装する5つのシンプルなステップ](https://qiita.com/taka_yayoi/items/f644b9c6d01feb853ab1)
- [Data Modeling Best Practices & Implementation on a Modern Lakehouse](https://www.databricks.com/blog/2022/10/20/data-modeling-best-practices-implementation-modern-lakehouse.html)
- [What's a Dimensional Model and How to Implement It on the Databricks Lakehouse Platform](https://www.databricks.com/blog/2022/11/07/load-edw-dimensional-model-real-time-databricks-lakehouse.html)

# レイクハウスでのディメンションモデルの構築をスタートする

[14日間のDatabricks無料トライアル](https://databricks.com/jp/try-databricks)

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)