青の統計学-DS Playground-

Mart 設計の基本:grain を決める

Stage 3 — 第2章 | dbt入門カリキュラム 推定学習時間:35〜45分 | 難易度:★★★☆☆


この章で学ぶこと

第1章 で intermediate が 「何を数えるか」 を固定しました。 次は BI が読む mart 層 の設計です。mart は「集計 SQL の置き場」ではなく、組織が会議で使う数字の商品棚 です。

データマートの考え方 では、再利用可能な分析用表の一般論を学びました。 dbt ではさらに踏み込み、1 mart = 1 business question = 1 grain を原則にします。

まず dbt の作法を整理し、続けて DS Playground の mart ファミリーと _product__marts.yml を読み解きます。

この章を終えると、こんなことができるようになります:

  • 「1 mart = 1 business question」の原則を、実モデル名で説明できる
  • Membership / Activity / Engagement など mart ファミリー を区別できる
  • grain(1 行の意味)と caveats(注意書き)を YAML から読み取れる
  • ワイルドマートを避ける判断基準を データマネジメント入門 と接続できる

mart 層の位置づけ

Medallion 三層 の流れの最終段が mart です。

flowchart LR STG["staging
view"] INT["intermediate
view"] MART["marts
table"] STG --> INT --> MART
典型マテリアライズ 責務
staging view ソースに近い薄い整形
intermediate view 指標定義の SSOT
mart table BI 向け完成品(grain 固定・集計済み)

mart の入力は intermediate または staging ですが、KPI 定義は intermediate に寄せ、mart では grain を決めて集計する のが基本です。


なぜ mart を分けるのか

1 表に複数の grain や目的を詰め込む ワイルドマート は、BI 利用者が「どの列を同じ行で見ていいか」分からなくなります。

-- アンチパターン: 1 枚の「なんでも KPI 表」
          select
            date_day,
            total_members,
            active_users,
            paid_conversion_rate,
            avg_engagement_score,
            primary_goal,
            problem_accuracy_rate
          from some_mega_mart;  -- grain が混在し、説明不能
          

ワイルドマートと SSOT で学んだ「属人 SQL の乱立」と同型の問題が、1 枚の mart にも起きます。

mart を分ける判断基準は 3 つです。

  1. business question が 1 文で言えるか … 「日次の DAU は?」と「ユーザーごとのエンゲージメント tier は?」は別の問い
  2. grain が 1 行の定義で固定できるか … 1 行 = 1 日、1 行 = 1 ユーザー × 1 日、など
  3. 既存 mart を拡張して grain が壊れないか … 列追加より 新表 の方が安全なことが多い

grain と YAML メタデータ

mart の YAML には、SQL だけでは伝わらない 定義の契約 を書きます。

meta キー 役割
business_question この表が答える 唯一の主問い
grain JOIN や SUM の前提(1 行 = 何か)
membership_definition / 指標定義 指標定義 の dbt 版
caveats 数字を説明するときの 但し書き
pii_level ガバナンス境界

SQL を写経するより YAML を先に読む 習慣が重要です。 Metabase 利用者は decision_use や caveats を見れば、その表を会議で使うべきか判断できます。


マテリアライズ方針

テーブル・ビュー・MV で学んだ物理化の選択が、dbt では materialized config になります。

マテリアライズ 理由
Staging view ソースに近い定義を常に最新反映
Intermediate view SSOT ロジックの単一化。再計算コストは mart 側で吸収
Mart table BI が安定・軽量に読む。毎回 view チェーンを辿らない

例外として、行数や更新頻度に応じて mart を incremental table にするケースがあります(第5章)。 「BI 向けに軽い完成品を置く」という レイク・DWH・マート の考え方と一致します。


Exposure との接続

メタデータとリネージ では、利用面まで lineage を伸ばす重要性を学びました。 dbt では exposures.yml に、ダッシュボード想定ごとに どの mart を読むか を宣言します。

mart 設計と exposure はセットです。 「このダッシュボードはどの mart に依存するか」がコード上で追えると、mart 変更時の影響範囲が見えます。


新しい mart を足すときのチェックリスト

  1. business question は 1 文で言えるか
  2. grain は 1 行の定義で固定できるか
  3. 既存 mart を拡張せず新表にすべきか(列追加で grain が壊れないか)
  4. caveats を YAML に書いたか
  5. singular test が必要か(例: catalog カバレッジ)
  6. どの exposure / ダッシュボードが依存するか
flowchart TB Q["business question
は 1 文か?"] G["grain は
固定できるか?"] N["新表が必要か?"] Y["YAML に
caveats を書く"] T["test / exposure
を更新"] Q --> G --> N --> Y --> T

mart ファミリー

DS Playground では、mart を ビジネス問い(business question)ごとに 1 表 で管理します。 overview.mdsemantic_ontology.md が示すファミリーは次のとおりです。

ファミリー 答える問い 主な mart 典型 grain
Membership 会員数は何人で、日々どれだけ増えるか fct_membership_daily 1 行 = 1 日
Monetization Premium への転換はどう進むか fct_membership_conversion_daily 1 行 = 1 日
Activity 明示的学習行動は何人分あるか fct_active_users_daily, fct_active_users_daily_by_member_status, fct_activity_events_daily_by_type 日 × (任意で status/type)
Period Activity DAU/WAU/MAU の推移は fct_active_users_period_summary 期間種別 × 期間開始日
Engagement 利用の深さ・広さ・休眠は fct_user_engagement_current, fct_user_engagement_distribution_current 1 行 = 1 会員(匿名キー)または分布セル
Demand 学習目的・調査ニーズは fct_learning_goal_share, fct_member_survey_option_share 目標または survey × 選択肢
Content Quality どの問題・カテゴリをレビューすべきか fct_problem_quality, fct_problem_category_quality 1 行 = 1 問題または 1 カテゴリ
Skill Check スキルチェック完了の推移は fct_skill_check_daily 1 行 = 1 日
flowchart LR F["Product mart
families"] I1["Intermediate
int_user_activity_events"] I2["Intermediate
int_member_status_current"] M1["Membership
fct_membership_daily"] A1["Activity
fct_active_users_daily"] A2["Activity
fct_active_users_daily_
by_member_status"] A3["Activity
fct_activity_events_daily_
by_type"] E1["Engagement
fct_user_engagement_current"] E2["Engagement
fct_user_engagement_
distribution_current"] F -.-> M1 F -.-> A1 F -.-> E1 I1 --> A1 I1 --> A2 I2 --> A2 I1 --> A3 I2 --> E1 E1 --> E2 classDef intermediate fill:#eff6ff,stroke:#2563eb,color:#1f2937 classDef membership fill:#fefce8,stroke:#ca8a04,color:#1f2937 classDef activity fill:#f0fdf4,stroke:#16a34a,color:#1f2937 classDef engagement fill:#faf5ff,stroke:#9333ea,color:#1f2937 class I1,I2 intermediate class M1 membership class A1,A2,A3 activity class E1,E2 engagement

_product__marts.yml の読み方

fct_membership_daily の YAML 抜粋(概念):

meta キー 読み方
business_question 「日別に、規約同意済み会員は何人まで増えているのか」 この表が答える 唯一の主問い
grain 1行 = 1日 JOIN や SUM の前提
membership_definition terms 同意 proxy 指標定義の dbt 版
caveats Auth 直読みしない、退会で累計から外れる 数字を説明するときの 但し書き
pii_level PII なし ガバナンス境界

dbt_project.yml では、staging / intermediate は view、mart は table がデフォルトです。 例外として fct_activity_events_daily_by_typeincremental table第5章 で詳述)です。

Exposure の例

exposures.yml では、Metabase ダッシュボード想定ごとに どの mart を読むか が宣言されています。

Exposure 読む mart 群 目的
metabase_product_health_dashboard membership + activity + engagement 分布など 有料化前プロダクトヘルス
metabase_pre_monetization_research_dashboard survey + content quality 学習目的・教材レビュー

よくある誤解

誤解 実際
「mart は便利な VIEW の集まり」 BI 向け 完成品。table マテリアライズが基本
「1 表に KPI を全部入れた方が楽」 grain が混在し、説明不能なワイルドマートになる
「YAML は飾り」 business question / caveats は 会議で使う数字の契約

体系コラム:カリキュラム上の位置づけ

項目 内容
Stage / 章 Stage 3 — 第2章
今回の論点 mart ファミリー、grain、YAML メタデータ、table マテリアライズ
前章との接続 中間モデル SSOT
次章への伏線 Membership mart — proxy 定義の具体例

まとめ

mart は 1 business question = 1 grain = 1 表 で設計します。 staging(view) → intermediate(view) → mart(table) の流れの最終段で、BI が安定・軽量に読める完成品を置きます。

YAML に business question・grain・caveats を書き、exposure でダッシュボード lineage まで伸ばす——これが dbt における mart 設計の基本です。 DS Playground では Membership / Activity / Engagement などファミリーごとに表を分け、定義の混線を防いでいます。


関連教材


確認問題

問題 1

mart を table として materialize する主な理由として最も適切なのはどれですか。

A. OLTP スキーマの書き込み権限を増やすため
B. BI が安定・軽量に完成品を読めるようにするため
C. staging の列名を隠すため
D. PII を自動的に削除するため

正解: B

解説: mart は BI 向け完成品。view チェーンの都度再計算を避けます。


問題 2

日次の人数 mart と、ユーザー単位の深度指標 mart を 別モデル にする理由として最も本質的なのはどれですか。

A. SQL が長いから
B. grain と business question が異なるから
C. YAML が書けないから
D. incremental だから

正解: B

解説: 前者は 日次 grain、後者は ユーザー grain。1 表に混ぜると grain が壊れます。


問題 3

モデル YAML の caveats(注意書き)の役割として最も近いのはどれですか。

A. SQL のインデントを統一する
B. 数字を説明するときの前提・限界を利用者に伝える
C. GitHub Actions の実行時間を短縮する
D. BI ツールの色設定を決める

正解: B

解説: caveats は ガバナンスと説明責任 のためのメタデータです。


用語メモ(この章)

用語 意味(この章での使い方)
mart BI 向け完成表。grain 固定・集計済み
grain 1 行が表す意味(1 日、1 ユーザー × 1 日 など)
business question mart が答える唯一の主問い
caveats 数字を説明するときの前提・限界
mart ファミリー Membership / Activity など問いのカテゴリ
exposure ダッシュボードと mart の依存関係宣言