EXERCISE 90分

ストーリー

田中VPoE
データレイク、DWH、レイクハウス、ディメンショナルモデリング。ストレージからモデリングまで一通り学んだ。実際のシナリオでDWHを設計してもらう
あなた
Step 1のDataFlow社のシナリオの続きですか?
田中VPoE
そうだ。DataFlow社のデータ基盤をゼロから設計する。ストレージ構成、テーブル設計、dbtモデル、クエリ最適化まで一貫した設計書を作ってくれ
あなた
Medallionアーキテクチャを使って、Bronze/Silver/Goldの各層を設計します
田中VPoE
ビジネス要件を満たすディメンショナルモデルを設計してくれ。特に「アクティブユーザー」の定義を統一し、複数部門から信頼されるSingle Source of Truthを作ることが目標だ

ミッション概要

項目内容
演習タイトルデータウェアハウスの設計
想定時間90分
成果物DWH設計書(ストレージ設計 + ディメンショナルモデル + dbtモデル)
対象企業DataFlow社(Step 1から継続)

ビジネス要件

DataFlow社のビジネス要件:

1. KPI統一
   - アクティブユーザー: 過去30日間に1回以上ログインしたユーザー
   - チャーン率: 月初のアクティブユーザーのうち、月末に非アクティブになった割合
   - MRR: 当月の有効サブスクリプション × 月額料金の合計
   - NRR: (期首MRR + 拡大MRR - 縮小MRR - 解約MRR) / 期首MRR

2. 分析ユースケース
   - 日次売上レポート(翌朝9時までに提供)
   - 顧客セグメント別のLTV分析
   - キャンペーン効果測定(配信→開封→クリック→コンバージョン)
   - チャーン予測モデルの学習データ

3. パフォーマンス要件
   - ダッシュボードのクエリ応答: 10秒以内
   - 日次バッチの完了: 朝8時までに
   - データ保持期間: 3年間

Mission 1: ストレージ構成の設計

要件

DataFlow社のデータレイクとDWHのストレージ構成を設計してください。

  1. データレイクのディレクトリ構造を設計する
  2. パーティショニング戦略を定義する
  3. ファイルフォーマットとライフサイクルポリシーを決定する
解答例

ディレクトリ構造

s3://dataflow-data-lake/
├── bronze/
│   ├── app_db/          # PostgreSQL CDC
│   │   ├── users/
│   │   ├── subscriptions/
│   │   ├── campaigns/
│   │   └── email_deliveries/
│   ├── event_logs/      # MongoDB
│   │   └── clickstream/
│   ├── salesforce/      # Fivetran
│   │   ├── accounts/
│   │   └── opportunities/
│   ├── hubspot/         # Fivetran
│   │   └── leads/
│   └── stripe/          # Fivetran
│       ├── invoices/
│       └── subscriptions/
├── silver/
│   ├── users/
│   ├── subscriptions/
│   ├── events/
│   ├── campaigns/
│   └── payments/
├── gold/
│   ├── dimensions/
│   │   ├── dim_customer/
│   │   ├── dim_date/
│   │   ├── dim_plan/
│   │   └── dim_campaign/
│   ├── facts/
│   │   ├── fact_subscription/
│   │   ├── fact_user_activity/
│   │   └── fact_campaign_performance/
│   └── marts/
│       ├── revenue_daily/
│       ├── customer_ltv/
│       └── churn_features/
└── _system/
    ├── data_quality/
    └── audit_logs/

パーティショニング

テーブルパーティションクラスタリング
fact_user_activityactivity_date (DATE)customer_key
fact_subscriptioneffective_date (DATE)customer_key, plan_key
fact_campaign_performancesend_date (DATE)campaign_key

フォーマット・ライフサイクル

フォーマット0-90日90-365日1年以上
BronzeParquetStandardStandard IAGlacier IR
SilverParquetStandardStandardStandard IA
GoldParquetStandardStandardStandard

Mission 2: ディメンショナルモデルの設計

要件

DataFlow社のビジネス要件を満たすスタースキーマを設計してください。

  1. ファクトテーブルを3つ以上設計する
  2. ディメンションテーブルを4つ以上設計する(コンフォームドディメンション含む)
  3. SCD Type 2を1つ以上のディメンションに適用する
  4. 「アクティブユーザー」「MRR」「チャーン率」を計算するために必要なモデルを設計する
解答例

ER図

                 ┌─────────────┐
                 │  dim_date   │
                 └──────┬──────┘

  ┌─────────────┐  ┌────┴────────────┐  ┌──────────────┐
  │ dim_customer │──│ fact_subscription│──│  dim_plan    │
  │ (SCD Type 2)│  └────┬────────────┘  └──────────────┘
  └──────┬──────┘       │
         │         ┌────┴────────────────┐
         ├─────────│ fact_user_activity   │
         │         └─────────────────────┘

         │         ┌────────────────────────┐  ┌──────────────┐
         └─────────│ fact_campaign_perform.  │──│ dim_campaign │
                   └────────────────────────┘  └──────────────┘

ファクトテーブル

テーブル名粒度メジャー
fact_subscription1行 = 1サブスクリプション期間mrr, arr, 契約日数
fact_user_activity1行 = 1ユーザー × 1日login_count, feature_usage_count, session_duration_sec
fact_campaign_performance1行 = 1配信 × 1受信者is_delivered, is_opened, is_clicked, is_converted

ディメンションテーブル

テーブル名SCD主要属性
dim_customerType 2customer_id, name, segment, industry, plan, created_at
dim_dateType 0full_date, year, quarter, month, is_weekend, is_holiday
dim_planType 1plan_name, monthly_price, annual_price, features
dim_campaignType 1campaign_name, channel, target_segment, start_date

Mission 3: dbtモデルの設計

要件

「アクティブユーザー数」「MRR」「チャーン率」を計算するdbt Goldモデルを設計してください。

  1. SQLクエリを記述する
  2. dbt testsを定義する
  3. ドキュメント(description)を記述する
解答例
-- models/gold/marts/mart_monthly_metrics.sql
-- 月次KPIメトリクス

{{ config(
    materialized='table',
    partition_by={'field': 'metric_month', 'data_type': 'date'}
) }}

WITH active_users AS (
    SELECT
        DATE_TRUNC(activity_date, MONTH) AS metric_month,
        COUNT(DISTINCT customer_key) AS active_user_count
    FROM {{ ref('fact_user_activity') }}
    WHERE login_count > 0
    GROUP BY 1
),

mrr AS (
    SELECT
        DATE_TRUNC(effective_date, MONTH) AS metric_month,
        SUM(mrr) AS total_mrr
    FROM {{ ref('fact_subscription') }}
    WHERE status = 'ACTIVE'
    GROUP BY 1
),

churn AS (
    SELECT
        metric_month,
        active_start,
        active_end,
        SAFE_DIVIDE(active_start - active_end, active_start) AS churn_rate
    FROM (
        SELECT
            DATE_TRUNC(d.full_date, MONTH) AS metric_month,
            COUNT(DISTINCT CASE
                WHEN ua_start.login_count > 0 THEN ua_start.customer_key
            END) AS active_start,
            COUNT(DISTINCT CASE
                WHEN ua_end.login_count > 0 THEN ua_end.customer_key
            END) AS active_end
        FROM {{ ref('dim_date') }} d
        LEFT JOIN {{ ref('fact_user_activity') }} ua_start
            ON ua_start.activity_date BETWEEN DATE_TRUNC(d.full_date, MONTH)
               AND DATE_ADD(DATE_TRUNC(d.full_date, MONTH), INTERVAL 29 DAY)
        LEFT JOIN {{ ref('fact_user_activity') }} ua_end
            ON ua_end.activity_date BETWEEN DATE_SUB(LAST_DAY(d.full_date), INTERVAL 29 DAY)
               AND LAST_DAY(d.full_date)
            AND ua_end.customer_key = ua_start.customer_key
        WHERE d.full_date = DATE_TRUNC(d.full_date, MONTH)
        GROUP BY 1
    )
)

SELECT
    a.metric_month,
    a.active_user_count,
    m.total_mrr,
    c.churn_rate
FROM active_users a
LEFT JOIN mrr m ON a.metric_month = m.metric_month
LEFT JOIN churn c ON a.metric_month = c.metric_month

dbt テスト定義

# models/gold/marts/schema.yml
models:
  - name: mart_monthly_metrics
    description: "月次KPIメトリクス。アクティブユーザー数、MRR、チャーン率を統合"
    columns:
      - name: metric_month
        description: "メトリクスの対象月(月初日)"
        tests:
          - not_null
          - unique
      - name: active_user_count
        description: "過去30日間に1回以上ログインしたユーザー数"
        tests:
          - not_null
          - dbt_utils.expression_is_true:
              expression: ">= 0"
      - name: total_mrr
        description: "月次経常収益(Monthly Recurring Revenue)"
        tests:
          - not_null
          - dbt_utils.expression_is_true:
              expression: ">= 0"
      - name: churn_rate
        description: "月次解約率"
        tests:
          - dbt_utils.accepted_range:
              min_value: 0
              max_value: 1

達成度チェック

観点達成基準
ストレージ設計Medallionアーキテクチャに基づくディレクトリ構造が設計されている
ディメンショナルモデルファクト3つ以上、ディメンション4つ以上、SCD Type 2が含まれている
dbtモデルKPI計算SQLが記述され、テストとドキュメントがある
ビジネス要件の充足アクティブユーザー、MRR、チャーン率の定義が統一されている

推定所要時間: 90分