1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Snowflake上でStar SchemaとData Vault を試してみる

1
Last updated at Posted at 2026-02-14

1. はじめに

SnowPro Advanced Architectの試験勉強を進める中で、「スタースキーマ(Star Schema)」と「Data Vault」という2つのモデリング手法についての問題に何度か遭遇しました。教科書的な定義は理解したものの、ふと 「実際にSnowflakeで動かしてみたら、挙動や運用の手触り感はどう違うんだろう?」 という疑問が湧きました。
そこで、理論を頭に入れるだけでなく、実機を使ってその差を検証してみました。

2. そもそも、何が違うのか?

2.1 Star Schema

  • イメージ: 「BIツールやエンドユーザーにそのまま渡せる完成品」
  • 構造: 事実(Fact)と属性(Dimension)を分離。
  • 利点: JOINが少なくて速い。誰が見ても直感的に理解できる。
  • 欠点: スキーマが固定的。属性追加のたびにテーブル再構築が必要。

2.2 Data Vault 2.0

  • イメージ: 「どんな変更も後付けで吸収できる、拡張性重視の設計」
  • 構造: Hub(ビジネスキー)、Link(関係)、Satellite(属性・履歴)の3要素。
  • 利点: 既存の構造を壊さずに横にテーブルを足すだけで拡張可能。
  • 欠点: 分析時に大量のJOINが必要。人間が直接クエリを書くには複雑。

3. 新属性の追加、どちらが「楽」か?

「注文データ」に「配送情報」を後付けするケースでの手間を比較しました。

3.1 共通のサンプルデータ

  • 既存データ (Orders): order_id, amount, order_date
  • 追加したいデータ (Shipping): order_id, shipping_status, carrier_name

3.2 Star Schema での対応

既存の FACT_ORDERS テーブルを拡張する場合、必ず既存リソースにも修正が必要になります。

① DDLの変更と物理的な書き換え

-- 1. カラム追加
ALTER TABLE FACT_ORDERS ADD COLUMN SHIPPING_STATUS STRING, CARRIER_NAME STRING;

-- 2. 過去データの埋め合わせ (Backfill)
-- テーブルに対して、別システムのデータをJOINしてUPDATE。
-- Snowflakeではマイクロパーティションの再構築が発生し、多額のクレジットを消費する可能性がある
UPDATE FACT_ORDERS f
SET f.SHIPPING_STATUS = s.SHIPPING_STATUS, f.CARRIER_NAME = s.CARRIER_NAME
FROM STG_SHIPPING s WHERE f.order_id = s.order_id;

② 既存ETLパイプラインの修正

既存のロード処理に「配送システムとの結合」を組み込む必要があります。この時、例えば注文1件に対し、配送ステータスが「集荷」と「配送中」の2件存在した場合、単純にJOINしてテーブルを更新しようとすると、「1行だったはずの注文データが、JOINの結果2行に増えてしまう」 という事故が起こりえます。修正には細心の注意を払う必要があります。

3.3 Data Vault での対応(独立した追加)

Data Vaultでは、既存のリソースには一切触れません。

① DDLの変更(新規作成のみ)

-- 既存の HUB_ORDERS や SAT_ORDERS は「無修正」
-- 新しい情報を入れるための箱を横に置くだけ
CREATE TABLE SAT_SHIPPING (
    order_id INT,
    shipping_status STRING,
    carrier_name STRING,
    load_date TIMESTAMP
);

② ETLパイプラインの独立

既存のパイプライン(注文ロード)はそのままで、新システム用のジョブを横に追加するだけです。

  • 既存ジョブ: 注文システム → HUB_ORDERS, SAT_ORDERS (無修正・継続)
  • 新規ジョブ: 配送システム → SAT_SHIPPING (新規作成・並列実行)

DataVaultだと楽なポイント

  1. 物理的な影響ゼロ: 既存の SAT_ORDERSを書き換える必要は全くありません。新しいテーブルを1つ作り、そこに配送データを入れるだけで済みます。
  2. 整合性の分離: 配送データに重複があっても、「売上が2倍になる」といった事故は、ストレージ層では物理的に発生しません。
  3. 精神的余裕: 既存の「売上ロードジョブ」には指一本触れません。新しく「配送ロードジョブ」を横で作るだけなので、万が一新しいジョブが失敗しても、既存の売上基盤が止まることはありません。

4. 分析クエリ性能検証

「当年の売上を、月 × 配送業者種別 × 配送完了有無 の粒度で集計する分析クエリ」でそれぞれのモデルの実行時間を比較しました。

4.1 検証条件

検証では、モデリング差による影響を明確にするため、以下の条件を揃えています。

  • クラウドDWH:Snowflake
  • Warehouse サイズ:X-SMALL
  • キャッシュ影響排除
    • USE_CACHED_RESULT = FALSE
    • Warehouse の SUSPEND / RESUME によるローカルキャッシュクリア
  • 同一データ件数・同一ビジネスロジック
  • Star Schema / Data Vault で 意味的に同等なクエリ

4.2 実行クエリ

Star Schema

Fact テーブルに対して、ディメンション(配送ステータス)でグルーピングする典型的なスタークエリ

SELECT
  SHIPPING_STATUS,
  SUM(AMOUNT) AS TOTAL_REVENUE
FROM FACT_ORDERS
GROUP BY SHIPPING_STATUS;

Data Vault

Hub / Sat を JOIN し、同一粒度・同一意味の集計を実施

SELECT
  s2.SHIPPING_STATUS,
  SUM(s1.AMOUNT) AS TOTAL_REVENUE
FROM HUB_ORDERS h
JOIN SAT_ORDERS_CORE s1
  ON h.ORDER_ID = s1.ORDER_ID
JOIN SAT_ORDERS_SHIPPING s2
  ON h.ORDER_ID = s2.ORDER_ID
GROUP BY s2.SHIPPING_STATUS;

4.3 検証結果

キャッシュを完全に排除した状態での実行時間は以下の通りです。

データ件数 Star Schema [ms] (初期化) Data Vault [ms] (初期化)
100万件 624 (207.79) 1,400 (103.6)
1,000万件 522 (15.66) 2,500 (27.5)
1億件 1,400 (35) 16,000 (64)

※ 括弧内は クエリプロファイルの項目「初期化」にかかった時間

想定通り分析クエリに関してはStarSchemaの方が圧倒的に効率がいい結果となりました。
特に1億件を超えるとDataVaultのJOINコストは無視できない差になっています。

5. 【考察】「初期化」にかかる時間の謎

今回の検証で不思議に思った点は、100万件(中規模)のクエリにおける **「初期化(Initialization)」時間が、1億件などの場合と比べて長かった点です。

初期化フェーズでは「実行プランの配布」「演算子用メモリの確保」「ノード間通信の確立」「メタデータに基づくスキャン範囲の特定」が行われます。この時間がデータ量の少ないケースで増大した要因を、以下の検証事実から考察します。

検証の前提条件と事実

  • キャッシュの排除: USE_CACHED_RESULT = FALSE を設定し、各計測直前にウェアハウスを SUSPEND することで、結果キャッシュおよびローカルディスクキャッシュを完全に排除。
  • データの再現性: CREATE OR REPLACE による再構築後、他件数の検証を挟んで再計測しても、初期化時間は一貫して長い数値を記録。
  • マイクロパーティション数: 100万件のデータは 「1つのマイクロパーティション」 に集約されていることを確認。

なぜ100万件(単一パーティション)の初期化が遅いのか

Snowflakeは大規模分散処理(MPP)を前提とした設計であり、この設計思想と「単一マイクロパーティション」というデータの状態が、初期化フェーズにおける実行管理に影響を与えていると推測されます。

  1. 非対称なタスクマッピングの決定コスト
    1億件(多数のパーティション)の場合、ウェアハウスの全スレッドに対して均等にスキャンタスクを割り振る「定型的な並列実行プラン」が即座に確定されます。一方、100万件が1つのパーティションに収まっている場合、全スレッドのうち「どの特定のスレッドにスキャンを担当させ、残りのスレッドをどの演算子(Join等)の待機状態にするか」という 非対称なタスクマッピングの計算 が発生します。この「リソース割り当ての最適化」プロセスが、標準的なバルク処理よりも初期化時間を増大させている可能性があります。

  2. 小規模データにおける実行戦略の評価オーバーヘッド
    データが中規模(100万件程度)かつ単一パーティションの場合、オプティマイザは「Broadcast Join(全ノードへのコピー)」や「Local Join」など、複数の実行戦略のコストが僅差で並ぶ境界線上の判断を迫られます。1億件のように明らかにHash Join一択となる大規模データに比べ、最適な実行パスを選択・展開するためのロジック判定が初期化フェーズのオーバーヘッドとして現れていると推測されます。

6. まとめ

話が横道に逸れてしまいましたが、
検証結果として、分析クエリにおける応答性能は Star Schema が圧倒しており、一方でシステム変更やデータ追加に対する柔軟性は Data Vault 2.0 が極めて高いという、それぞれの設計思想通りの強みが確認できました。

  • Star Schema は、ユーザーに届けるための 分析性能(読み取り) に最適化されたモデル。
  • Data Vault 2.0 は、上流システムの変更やデータ追加による影響を最小化する 拡張性(運用) に優れたモデル。

それぞれの特性を理解したうえで、データの加工フェーズに応じて両者を併用することが、変化に強く、かつ高速なデータ基盤を構築する上で重要だと再認識することができました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?