📚

Databricksで構築するRedditデータパイプライン⑤ メトリクスビューによるセマンティックレイヤー

に公開

はじめに

前回(第4回)でパイプラインの基本構築は完了しました。今回からは発展編として、DatabricksのUnity Catalog メトリクスビューを紹介します。

第4回で作成したダッシュボードでは、Gold層のテーブルに直接クエリを書いていました。しかし、ダッシュボードが増えると、集計ロジックの散在カラム名の不統一が問題になります。

メトリクスビューは、これらの問題を解決するセマンティックレイヤーを提供します。


メトリクスビューとは

公式ドキュメント

詳細は公式ドキュメントを参照してください。

ひとことで言うと

メトリクスビューは、dimensions(分析軸)measures(集計値) を定義し、データモデルに意味付けを行う仕組みです。

なぜ必要なのか

問題 Gold層だけの場合 メトリクスビュー導入後
集計ロジックの散在 各ダッシュボードで同じSUMを書く メトリクスビューに一元化
カラム名の不統一 sum_upvote vs total_upvote display_name で統一
動的な分析軸の追加 テーブル定義の変更が必要 メトリクスビュー内で動的計算可能

本プロジェクトでの位置づけ

第3回で構築したDim/Factテーブルの上に、メトリクスビューを追加します。

Silver層

    ├──▶ Dim層
    │      dim_calendar, dim_subreddit, dim_post

    └──▶ Fact層
           fact_subreddit_daily, fact_post_daily

                ├──▶ Gold層(BI向け)
                │      gold_subreddit_daily, gold_top_posts_daily

                └──▶ メトリクスビュー(セマンティックレイヤー)  ← NEW!
                       reddit_metric_view

Gold層とメトリクスビューは併用します。用途に応じて使い分けます。

用途 使うもの
固定のダッシュボード Gold層テーブル
新しい集計軸の試行錯誤 メトリクスビュー
複雑なレポート(非定型) メトリクスビュー

メトリクスビューの作成

メトリクスビューはSQLエディタで直接作成できます。Databricks SQLのクエリエディタを開き、以下のSQLを実行するだけです。

SQLエディタで実行

USE CATALOG reddit;
USE SCHEMA sdp;

CREATE OR REPLACE VIEW reddit_metric_view
WITH METRICS
LANGUAGE YAML
AS $$
version: 1.1

source: fact_subreddit_daily

joins:
  - name: dim_calendar
    source: dim_calendar
    on: source.date_id = dim_calendar.date_id
  - name: dim_subreddit
    source: dim_subreddit
    on: source.subreddit_id = dim_subreddit.subreddit_id

dimensions:
  - name: subreddit
    expr: dim_subreddit.subreddit
    comment: サブレディット名(分析の主軸)
    display_name: サブレディット
  - name: calendar_date
    expr: dim_calendar.calendar_date
    comment: データ取込日
    display_name: 取込日
    format:
      type: date
      date_format: year_month_day
      leading_zeros: false
  - name: year
    expr: dim_calendar.year
    comment: 取込日の年
    display_name: 年
  - name: month
    expr: dim_calendar.month
    comment: 取込日の月
    display_name: 月
  - name: day
    expr: dim_calendar.day
    comment: 取込日の日
    display_name: 日
  - name: year_month
    expr: dim_calendar.year_month
    comment: 年月(YYYY-MM形式)
    display_name: 年月
  - name: day_of_week
    expr: dayofweek(dim_calendar.calendar_date)
    comment: 曜日(1=日曜, 7=土曜)
    display_name: 曜日
  - name: is_weekend
    expr: dayofweek(dim_calendar.calendar_date) IN (1, 7)
    comment: 週末フラグ(土日)
    display_name: 週末フラグ

measures:
  - name: total_post_count
    expr: SUM(post_count)
    comment: 投稿数の合計
    display_name: 投稿数_合計
  - name: total_row_count
    expr: SUM(row_count)
    comment: レコード数の合計
    display_name: レコード数_合計
  - name: total_upvote
    expr: SUM(sum_upvote)
    comment: Upvote数の合計
    display_name: Upvote数_合計
  - name: avg_upvote_per_post
    expr: AVG(avg_upvote)
    comment: 1投稿あたりの平均Upvote数
    display_name: Upvote数_投稿平均
  - name: avg_comment_upvote
    expr: AVG(avg_comment_upvote)
    comment: コメントの平均Upvote数
    display_name: コメントUpvote_平均
$$;

実行後、Catalog Explorerで reddit.sdp.reddit_metric_view が作成されていることを確認できます。


YAML定義の解説

要素 説明
source メインとなるFactテーブル
joins Dimensionテーブルとの結合定義
dimensions 分析軸(フィルタ・グループ化に使用)
measures 集計値(SUM, AVG, COUNT等)
display_name UIで表示される名前
comment 説明文
format 表示形式(日付のフォーマット等)
expr 計算式(元テーブルのカラムや関数を使用)

動的計算の例

day_of_weekis_weekend は、dim_calendar テーブルに存在しないカラムです。メトリクスビュー内で動的に計算しています。

# 元テーブルにないカラムも定義可能
- name: day_of_week
  expr: dayofweek(dim_calendar.calendar_date)  # 関数で動的計算
  comment: 曜日(1=日曜, 7=土曜)
  display_name: 曜日

💡 本来は事前計算が望ましい

日付関連の属性は頻繁に使うため、dim_calendar に事前計算しておく方がパフォーマンス面で有利です。今回は「メトリクスビューでも動的計算できる」ことを示すためにあえてこの形にしています。


(オプション)DABsによるデプロイ

メトリクスビューをAsset Bundleで管理したい場合は、ノートブック化してJobとしてデプロイできます。

ディレクトリ構成

reddit-pipeline/
├── src/
│   └── metric_views/
│       └── metric_view_creation.sql
└── resources/
    └── reddit_metric_views_setup_job.yml

src/metric_views/metric_view_creation.sql

パラメータ化するために identifier() 関数を使用します。Lakeflow Declarative Pipelinesのノートブックと同様に、MAGICコマンドなしで純粋なSQLで記述できます。

-- Databricks notebook source
USE CATALOG identifier(:catalog);
USE SCHEMA identifier(:schema);

-- COMMAND ----------

CREATE OR REPLACE VIEW reddit_metric_view
WITH METRICS
LANGUAGE YAML
AS $$
version: 1.1

source: fact_subreddit_daily

joins:
  - name: dim_calendar
    source: dim_calendar
    on: source.date_id = dim_calendar.date_id
  - name: dim_subreddit
    source: dim_subreddit
    on: source.subreddit_id = dim_subreddit.subreddit_id

dimensions:
  - name: subreddit
    expr: dim_subreddit.subreddit
    comment: サブレディット名(分析の主軸)
    display_name: サブレディット
  - name: calendar_date
    expr: dim_calendar.calendar_date
    comment: データ取込日
    display_name: 取込日
    format:
      type: date
      date_format: year_month_day
      leading_zeros: false
  - name: year
    expr: dim_calendar.year
    comment: 取込日の年
    display_name: 年
  - name: month
    expr: dim_calendar.month
    comment: 取込日の月
    display_name: 月
  - name: day
    expr: dim_calendar.day
    comment: 取込日の日
    display_name: 日
  - name: year_month
    expr: dim_calendar.year_month
    comment: 年月(YYYY-MM形式)
    display_name: 年月
  - name: day_of_week
    expr: dayofweek(dim_calendar.calendar_date)
    comment: 曜日(1=日曜, 7=土曜)
    display_name: 曜日
  - name: is_weekend
    expr: dayofweek(dim_calendar.calendar_date) IN (1, 7)
    comment: 週末フラグ(土日)
    display_name: 週末フラグ

measures:
  - name: total_post_count
    expr: SUM(post_count)
    comment: 投稿数の合計
    display_name: 投稿数_合計
  - name: total_row_count
    expr: SUM(row_count)
    comment: レコード数の合計
    display_name: レコード数_合計
  - name: total_upvote
    expr: SUM(sum_upvote)
    comment: Upvote数の合計
    display_name: Upvote数_合計
  - name: avg_upvote_per_post
    expr: AVG(avg_upvote)
    comment: 1投稿あたりの平均Upvote数
    display_name: Upvote数_投稿平均
  - name: avg_comment_upvote
    expr: AVG(avg_comment_upvote)
    comment: コメントの平均Upvote数
    display_name: コメントUpvote_平均
$$;

resources/reddit_metric_views_setup_job.yml

resources:
  jobs:
    reddit_metric_views_setup_job:
      name: reddit-metric-views-setup-${bundle.target}

      parameters:
        - name: catalog
          default: ${var.catalog}
        - name: schema
          default: ${var.schema}

      tasks:
        - task_key: metric_view_setup
          notebook_task:
            notebook_path: ../src/metric_views/metric_view_creation.sql
            base_parameters:
              catalog: "{{job.parameters.catalog}}"
              schema: "{{job.parameters.schema}}"
            source: WORKSPACE

      environments:
        - environment_key: default
          spec:
            environment_version: "4"

デプロイと実行

databricks bundle deploy
databricks bundle run reddit_metric_views_setup_job

💡 なぜ bundle run が必要なのか?

databricks bundle deployJobの定義をWorkspaceに登録するだけで、Jobを実行はしません

Lakeflow Pipelinesの場合はスケジュールを設定しているため、deploy後に自動で定期実行されます。しかし、メトリクスビューのセットアップJobは一度実行すればビューが作成されるため、スケジュールを設定していません。そのため、初回セットアップ時に手動で bundle run を実行する必要があります。

項目 Lakeflow Pipelines メトリクスビューJob
目的 データを継続的に処理 ビュー定義を1回作成
スケジュール あり(定期実行) なし(初回のみ)
bundle deploy スケジュールで自動実行 手動でrunが必要

メトリクスビューの活用

1. Databricks SQLからのクエリ

メトリクスビューをクエリする際は、measures(集計値)に MEASURE() 関数を使用する必要があります。

-- subreddit別の月次サマリ
SELECT
  subreddit,
  year_month,
  MEASURE(total_post_count) AS total_post_count,
  MEASURE(total_upvote) AS total_upvote,
  MEASURE(avg_upvote_per_post) AS avg_upvote_per_post
FROM reddit_metric_view
WHERE year = 2025
GROUP BY subreddit, year_month
ORDER BY year_month, total_upvote DESC;

💡 MEASURE() 関数について

メトリクスビューの measures はSUMやAVGなどの集計関数を含むため、通常のカラムとは異なります。MEASURE() 関数で囲むことで、メトリクスビューが定義した集計ロジックが適用されます。

また、GROUP BY で集計軸(dimensions)を指定する必要があります。これにより、どの粒度で集計するかを明示します。

2. ダッシュボードでの利用

AI/BI dashboardsでメトリクスビューをデータソースとして選択すると、dimensionsとmeasuresが明確に分かれて表示されます。これにより、グラフ作成時に「どのカラムをX軸に使うか」「どのカラムを集計するか」が直感的に選べます。

ダッシュボードでは MEASURE() 関数を意識する必要はなく、UIで measures を選択するだけで自動的に適切な集計が行われます。


今回のまとめ

発展編として、Unity Catalog メトリクスビューによるセマンティックレイヤーの構築を解説しました。

メトリクスビューのメリット:

メリット 説明
集計ロジックの一元化 measures でSUM/AVG等を定義
カラム名の統一 display_name でUI表示名を統一
動的な分析軸 expr で元テーブルにない計算も定義可能

構成のポイント:

要素 本プロジェクトでの設定
source fact_subreddit_daily
joins dim_calendar, dim_subreddit
dimensions subreddit, calendar_date, year等
measures total_post_count, total_upvote等

メトリクスビューを導入することで、第4回で作成したダッシュボードの基盤がより堅牢になります。


シリーズ目次:

  1. 概説 & プロジェクト準備
  2. データ取得の基本設計
  3. Lakeflow Spark Declarative Pipelines(Bronze→Silver→Gold)
  4. ダッシュボード & 運用
  5. メトリクスビューによるセマンティックレイヤー(本記事)
  6. Genieを使った分析

Discussion