dbt

NicheeLab: dbtで定義するdimensionsの基礎と分析軸の設計

2026-04-19
NicheeLab編集部

ディメンションは分析の“軸”であり、ファクトを意味付けする属性群です。dbtではモデル・スナップショット・テストを組み合わせて、安定したディメンションを構築します。

本稿はAnalytics Engineerの出題観点(モデリング、スナップショット、テスト、ドキュメント)を踏まえ、実務でそのまま使える設計パターンを解説します。

ディメンションの基本とdbtにおける役割

ディメンションは顧客・商品・日付などの属性テーブルで、分析時にグルーピング・フィルタの軸になります。ファクト(取引・イベント)と外部キーで結合し、スター・スキーマを形成します。

dbtでは、ディメンションを通常のモデルとして定義し、品質をスキーマテストで担保します。履歴を保持する場合はスナップショット(SCD2)を併用します。セマンティックな定義(粒度、キー、説明)をドキュメント化して、利用者が正しい解釈で参照できる状態を保つことが重要です。

  • ディメンションは安定した粒度(grain)と一意キーが必要
  • Type1(上書き)かType2(履歴保持)かを明確化
  • 外部キー関係(fact→dim)の関係テストを設定
  • ドキュメントでビジネス定義と使用例を明記
要素目的dbtでの実装ポイント
ディメンション表(顧客・商品・日付)分析の軸。属性を提供しグループ化・フィルタに使用モデルとして定義。surrogate key生成、not_null/uniqueテスト、必要に応じスナップショット
ファクト表(受注・決済・イベント)集計対象。メジャーの計算元増分モデルが多い。ディメンションの外部キー参照テストを設定
ブリッジ表(多対多中間)多対多関係の解消や階層の展開キーの複合一意性テスト、粒度の明記、結合順序のドキュメント化

スター・スキーマ(概念図)

dim_customercustomer_sk (PK)dim_productproduct_sk (PK)dim_datedate_sk (PK)fact_ordersorder_id (PK) / customer_sk, product_sk, order_date_sk (FK)3 つの次元テーブルが fact_orders にサロゲートキーで結合されるスター・スキーマ

シンプルなType1ディメンション(dim_customer.sql)

{{
  config(materialized='table')
}}

with src as (
  select
    source_system,
    customer_id,
    coalesce(trim(lower(email)), '') as email,
    trim(full_name) as full_name,
    status,
    first_order_date
  from {{ source('crm', 'customers') }}
),
latest as (
  -- 自然キーで最新のみを採用(重複除去例)
  select * from (
    select s.*,
           row_number() over(partition by source_system, customer_id order by _ingested_at desc) as rn
    from src s
  ) t where rn = 1
)
select
  {{ dbt_utils.surrogate_key(['source_system','customer_id']) }} as customer_sk,
  source_system,
  customer_id,
  email,
  full_name,
  status,
  first_order_date
from latest;

粒度とキー設計:自然キーとサロゲートキー

ディメンションの粒度は“行が一意に表す実世界の単位”です。顧客ディメンションなら「ソース×顧客ID」が自然キーになりやすく、これを安定化するためにサロゲートキー(ハッシュや連番)を採用します。

dbtではdbt_utils.surrogate_keyで複数列から安定ハッシュを生成できます。自然キーで重複を除去し、サロゲートキーにunique/not_nullテストをかけるのが基本パターンです。

  • 自然キーは業務システムの都合で変化する可能性がある
  • サロゲートキーは結合の安定性を高め、メタデータ移行にも強い
  • テストはnot_null、unique、(必要に応じ)関係テストをセットで

キーとテストの宣言(schema.yml 抜粋)

version: 2

models:
  - name: dim_customer
    description: 顧客ディメンション(Type1)。source_system×customer_id粒度。
    columns:
      - name: customer_sk
        tests:
          - not_null
          - unique
      - name: customer_id
        tests:
          - not_null
      - name: email
        description: 正規化済みメールアドレス

SCDの扱い:dbtスナップショットでType2履歴を管理

属性履歴を保持したい場合、dbtのスナップショットを使ってSCD Type2を実装します。チェック対象カラムが変化したときに新しい行を挿入し、valid_from/valid_toで有効期間を管理します。

実務では、履歴保持用スナップショット(生の履歴)と、最新有効行だけを返す現在値ディメンション(便利用)を分けておくと集計が安定します。

  • strategy='check' は複数列の変更検知に向く
  • unique_key は自然キーを指定(例: source_system+customer_id)
  • invalidate_hard_deletes で物理削除も履歴化
  • 最新行ビューを別モデルで提供して結合を簡潔に

顧客SCD2スナップショット(snapshots/dim_customer_scd2.sql)

{% snapshot dim_customer_scd2 %}

{{
  config(
    target_schema='snapshots',
    unique_key='concat(source_system, ''::'', customer_id)',
    strategy='check',
    check_cols=['email','full_name','status'],
    invalidate_hard_deletes=True
  )
}}

select
  source_system,
  customer_id,
  lower(email) as email,
  full_name,
  status
from {{ source('crm', 'customers') }}

{% endsnapshot %}

-- 最新有効行のみの便利用ディメンション(models/dim_customer_current.sql)
{{
  config(materialized='view')
}}
select *
from {{ ref('dim_customer_scd2') }}
where dbt_valid_to is null

ロールプレイングとコンフォームド・ディメンション

同一ディメンションを文脈に応じて複数の役割で利用するのがロールプレイングです。代表例は日付ディメンションを受注日・出荷日などで使い分けるパターンです。

複数データマート間で同一解釈を維持するコンフォームド・ディメンションは、単一のソースモデルを参照し、ビュー層でカラム名のロールに応じたエイリアスを付けると運用が簡潔です。

  • 基底ディメンションは1つに集約、役割ビューで命名を文脈化
  • テストは基底側に集約、ビュー側は軽量に保つ
  • ビジネス定義は基底モデルのドキュメントで一元管理

ロールプレイング日付ディメンション(ビュー)

{{
  config(materialized='view')
}}
-- models/dim_order_date.sql
select
  date_sk   as order_date_sk,
  date_day  as order_date,
  year,
  month,
  week,
  is_weekend
from {{ ref('dim_date') }};

{{
  config(materialized='view')
}}
-- models/dim_ship_date.sql
select
  date_sk   as ship_date_sk,
  date_day  as ship_date,
  year,
  month,
  week,
  is_weekend
from {{ ref('dim_date') }};

日付ディメンションの設計:date_spineと時間階層

日付ディメンションは分析の中核です。欠損日のない連続軸(spine)を生成し、年・四半期・月・週・営業日フラグなどの派生列を付与します。連続軸は期間集計・ゼロ埋めに必須です。

dbt_utilsのdate_spineを使うとDWH差異を吸収して日付系列を生成できます。開始・終了日時は運用ポリシー(遡及範囲、将来日付の有無)に合わせて定義します。

  • 日付キーは整数(YYYYMMDD)やサロゲートキーを採用しやすい
  • タイムゾーンの決め打ちとドキュメント化を忘れない
  • 営業日カレンダーは別テーブルでマスタ管理すると拡張しやすい

日付ディメンション(dim_date.sql)

{{
  config(materialized='table')
}}
with spine as (
  {{ dbt_utils.date_spine(
      datepart='day',
      start_date="to_date('2018-01-01')",
      end_date='current_date'
  ) }}
),
cal as (
  select
    cast(replace(cast(date_day as string), '-', '') as bigint) as date_sk,
    date_day,
    extract(year from date_day) as year,
    extract(quarter from date_day) as quarter,
    extract(month from date_day) as month,
    extract(week from date_day) as week,
    case when extract(dayofweek from date_day) in (6,7) then true else false end as is_weekend
  from spine
)
select * from cal

テストとドキュメント:品質を支える最小セット

ディメンションは“変わらない軸”としての信頼性が重要です。キーの一意性・NULL禁止・関係の整合をスキーマテストで強制し、モデル説明やカラム定義、粒度、更新方針をドキュメント化します。

試験対策では、どのテストをどこに設定すべきか(dim側のunique/not_null、fact側のrelationships)がよく問われます。実務では、CIでスナップショット・モデル・テストを定期実行し、破壊的変更をdocsとカタログで可視化する運用が有効です。

  • dim: surrogate keyにunique/not_null
  • fact: 外部キーにrelationships(dimのキー参照)
  • docs: 粒度、キー、更新頻度、SCD方針、使用例を明記

関係テストとドキュメント(schema.yml 抜粋)

version: 2

models:
  - name: fact_orders
    description: 受注ファクト(日次増分)
    columns:
      - name: customer_sk
        tests:
          - relationships:
              to: ref('dim_customer')
              field: customer_sk
      - name: product_sk
        tests:
          - relationships:
              to: ref('dim_product')
              field: product_sk
      - name: order_date_sk
        tests:
          - relationships:
              to: ref('dim_date')
              field: date_sk

  - name: dim_product
    description: 商品ディメンション。粒度=product_id。価格などの履歴は別テーブルで管理。
    columns:
      - name: product_sk
        description: サロゲートキー
        tests: [not_null, unique]
      - name: product_id
        description: 自然キー(ソース依存)
        tests: [not_null]

問題で確認

Analytics Engineer

問題 1

受注ファクトに対して、顧客ステータスの履歴を“当時の値”で分析したい。dbtの設計として最も適切なのはどれか。

  1. 顧客ディメンションをスナップショット(SCD2)で管理し、fact_ordersの受注日で有効行に結合する
  2. 顧客ディメンションを常に上書き(Type1)し、最新のステータスで結合する
  3. fact_ordersに顧客の全属性をデノーマライズして保持する
  4. 受注日ごとに顧客ディメンションをフルリフレッシュで作り直す

正解: A

“当時の値”が必要なためSCD2が適切。スナップショットで有効期間を管理し、受注日が有効期間内の顧客行に結合する。Type1や常時デノーマライズでは履歴が失われ、日次フルリフレッシュはコスト・安定性の面で非効率。

よくある質問

ディメンションとエンティティテーブルは同じですか?

近い概念ですが目的が異なります。エンティティは業務データの正規化表現で、ディメンションは分析用に“軸”として最適化した表です。ディメンションでは分析に不要な列の削除、コード値の正規化、派生列の追加、サロゲートキー化、SCDの適用などを行います。

SCD2は必ずスナップショットで実装すべきですか?

dbtではスナップショットが安全で標準的です。DWHの変更データキャプチャ(CDC)を直接使う選択肢もありますが、移植性や一貫したテーブル構造(valid_from/valid_to、dbt_updated_at等)を重視するならスナップショットが扱いやすいです。

遅延到着ファクトはどう扱いますか?

ファクトのイベント日付に基づいてロールプレイング日付ディメンションに結合し、必要に応じて再集計(再実行)を許容する設計にします。ディメンション側はSCD2で“当時の属性”に結合できるよう有効期間を管理し、増分モデルでは過去再計算の再取り込みウィンドウを設けます。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
dbt

dbt Model の基礎: SQL で定義する変換の最小単位

Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...

dbt

dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点

dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...

dbt

dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点

dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...

dbt

dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト

Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....

dbt

dbt_project.yml の読み方:主要設定と命名を最短で掴む

dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...

dbtの記事一覧 (100件)
© 2026 NicheeLab All rights reserved.