snapshots と exposures:履歴化と下流利用者管理
Stage 5 — 第2章 | dbt入門カリキュラム 推定学習時間:40〜50分 | 難易度:★★★★☆
この章で学ぶこと
mart は 現時点の SSOT ですが、運用には 「いつ変わったか」 と 「誰がどの表を使うか」 も必要です。
まず dbt snapshot と exposure の作法を整理し、続けて DS Playground の snapshot_user_learning_preferences と models/exposures.yml を読み解きます。
この章を終えると、こんなことができるようになります:
- timestamp strategy snapshot の config を読める
- snapshot が mart に未接続でも価値がある理由を説明できる
- exposure が メタデータとリネージ をどう伸ばすか説明できる
- 2 つの Metabase exposure の depends_on 差を説明できる
snapshot とは何か
ソースが current-state(最新状態だけを保持)のとき、mart は build 時点のスナップショットしか見えません。 ユーザー属性が変わっても、過去の mart 行は 遡及更新されません。
将来「月次で構成がどう変わったか」を見るには 履歴テーブル が必要です。
| 方式 | 特徴 |
|---|---|
| アプリ側 event 履歴 | 正攻法。アプリ改修が必要 |
| dbt snapshot | ソースが current-state のまま履歴を後付け |
dbt snapshot は SCD(Slowly Changing Dimension) を warehouse 上に作る機能です。
strategy='timestamp' では、変更検知列(例: updated_at)の変化で新しい履歴行を追加します。
ソース / staging"] SNAP["snapshot
(履歴テーブル)"] MART["current-state mart
(現時点の集計)"] FUTURE["将来の推移 mart
(任意)"] SRC --> SNAP SNAP -.-> FUTURE SRC --> MART
データマネジメント入門 の「保存期間と改訂履歴」が snapshot に相当します。
exposure とは何か
dbt の exposure は、プロジェクト外の 利用面(ダッシュボード、Notebook、逆 ETL)を lineage グラフに載せる機能です。
dbt docs generate の lineage 上で mart → exposure の矢印が見えます。
| 効果 | 説明 |
|---|---|
| 影響範囲分析 | mart 変更時に どのダッシュボードが壊れるか |
| オーナーシップ | owner.email で問い合わせ先 |
| ドキュメント | docs artifact で利用者向け索引 |
| SSOT | 「この会議はこの exposure の mart セットを見る」と合意 |
Harness Engineering と DM の「外部利用面のハーネス」に近い考え方です。
snapshot 運用上の注意
- snapshot も build 対象 — 日次 workflow で増える
- PII — ユーザー ID を含む場合は内部 schema のみ
- mart との二重 SSOT — 現在値は mart、履歴は snapshot と 役割分担 を YAML に書く
- full-refresh — snapshot 再構築は慎重に(履歴消失リスク)
snapshot と current-state mart は 役割が異なります。 snapshot は履歴 as-of 用、mart は build 時点の集計用——混同しないことが重要です。
snapshot_user_learning_preferences
fct_learning_goal_share は 現在の primary_goal だけを見ます。
ユーザーが goal を変更しても、過去の構成比 mart は遡及更新されません。
教学例として、学習目的の履歴化 snapshot を置いています。
{% snapshot snapshot_user_learning_preferences %}
{{
config(
target_schema=target.schema,
strategy='timestamp',
unique_key='user_id',
updated_at='updated_at',
invalidate_hard_deletes=True
)
}}
select
user_id,
primary_goal,
preference_source,
created_at,
updated_at
from {{ ref('stg_supabase__user_learning_preferences') }}
{% endsnapshot %}
config の読み方
| 設定 | 意味 |
|---|---|
strategy='timestamp' |
updated_at 変化で新 SCD 行 |
unique_key='user_id' |
1 ユーザー 1 現行行の追跡 |
invalidate_hard_deletes=True |
ソースから消えた行を snapshot 上で無効化 |
(current)"] --> SNAP["snapshot_user_learning_preferences
(history)"] SNAP -.->|将来| MART["goal 推移 mart(未実装)"] STG --> FCT["fct_learning_goal_share
(現在構成のみ)"]
snapshot を将来 mart に接続するか、教学例のままにするかはプロジェクト方針で決めます。 mart に未接続でも、履歴テーブルとしての価値(将来の as-of 分析の土台)はあります。
exposures.yml
Metabase ダッシュボード想定ごとに どの mart を読むか を宣言しています。
exposures:
- name: metabase_product_health_dashboard
type: dashboard
depends_on:
- ref('fct_membership_daily')
- ref('fct_active_users_daily')
# ...
owner:
name: "BlueBayes / DS Playground"
email: "analytics@bluebayes.jp"
2 つの dashboard exposure
metabase_product_health_dashboard — 有料化前プロダクトヘルス
| 依存 mart(例) | ファミリー |
|---|---|
fct_membership_daily, fct_membership_conversion_daily |
Membership / Monetization |
fct_active_users_daily, fct_active_users_daily_by_member_status |
Activity |
fct_activity_events_daily_by_type |
Activity mix |
fct_active_users_period_summary |
DAU/WAU/MAU |
fct_skill_check_daily |
Skill check |
fct_user_engagement_distribution_current |
Engagement |
metabase_pre_monetization_research_dashboard — 学習目的・調査・教材品質
| 依存 mart | ファミリー |
|---|---|
fct_learning_goal_share, fct_member_survey_option_share |
Demand |
fct_problem_quality, fct_problem_category_quality |
Content quality |
exposure の maturity は medium です。
ダッシュボード URL は作成後に YAML へ追記する運用です。
体系コラム:カリキュラム上の位置づけ
| 項目 | 内容 |
|---|---|
| Stage / 章 | Stage 5 — 第2章 |
| 今回の論点 | SCD snapshot、dashboard lineage、2 exposure の分割 |
| 前章との接続 | safe_ratio マクロ |
| 次章への伏線 | CI / docs / Capstone |
まとめ
dbt は warehouse 内の transform だけでなく、履歴(snapshot)と利用面(exposure) までモデルグラフに載せられます。
DS Playground では、current-state mart と snapshot の役割分担、ヘルス vs リサーチの exposure 分割——という運用設計がコード上で可視化されています。
関連教材
- 前章: safe_ratio マクロ
- 次章: CI / docs / Capstone
- 関連(DM): メタデータとリネージ
確認問題
問題 1
strategy='timestamp' の snapshot で、新しい snapshot 行が作られる典型トリガーはどれですか。
A. 毎日 0 時に無条件
B. ソースの updated_at(等の変更検知列)が変わったとき
C. BI ツールが更新されたとき
D. seed が変わったとき
正解: B
問題 2
exposure を _exposures.yml に定義する 主な目的 として最も近いのはどれですか。
A. SQL を短くする
B. mart 変更の影響がダッシュボード等に及ぶことを lineage で可視化する
C. OLTP の RLS を設定する
D. incremental lookback を決める
正解: B
問題 3
snapshot と current-state mart の関係について 正しい 説明はどれですか。
A. snapshot は mart の代替で、current-state mart は不要
B. snapshot は履歴 as-of 用、current-state mart は build 時点のスナップショット用
C. どちらも BI から直接 source() を読む
D. snapshot は seed の別名
正解: B
用語メモ(この章)
| 用語 | 意味(この章での使い方) |
|---|---|
| snapshot | current-state ソースから SCD 履歴テーブルを作る dbt 機能 |
| timestamp strategy | 変更検知列の変化で新履歴行を追加する方式 |
| current-state | build 時点の最新状態。過去 as-of 不可 |
| exposure | ダッシュボード等の利用面を lineage に載せる宣言 |
| SCD | 属性の変化を履歴として保持する次元設計 |