12
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

dbtの新しいセマンティックレイヤー「MetricFlow」を触ってみた

Last updated at Posted at 2023-05-26

はじめに

dbtのセマンティックレイヤーに今後組み込まれる予定であるMetricFlowについて、実際にインストールしてtutorialを試してみました🦄
dbtでは、これまでdbt_metricsというメトリック管理用のパッケージが採用されていましたが、今後それが廃止になり、MetricFlowに移行になります。

dbtとは

dbt Semantic Layerとは

簡単に言えば、「収益みたいなビジネス指標を計算するロジックをいろんなツール上でバラバラにやるんじゃなくて切り出してdbtで管理しようぜ」 ってやつです。

MetricFlowとは

dbt_metrics から MetricFlowへ

dbtはセマンティックレイヤーの中で使用していたdbt_metricsというパッケージを廃止してMetricFlowを採用することを発表しました。

dbtの開発元であるdbt Labs社は、2023年2月にMetricFlowの開発会社であるTransform社を買収しています。

なぜdbt_metricsパッケージを廃止するのかについては以下の記事が参考になります。

セマンティックレイヤーの開発をする上で、先行しているMetricFlowを取り入れた方が実現が早まるということですね。

dbt_metricsは、7 月下旬の dbt-core v1.6 のリリースに伴いサポートが廃止される予定です。

MetricFlowで何ができるか?

1. JOINに対応

image.png
www.getdbt.comより引用

メトリクスの計算にJOINが使えるようになります。
これは便利そうですね。

2. データ プラットフォームのサポートの拡張

現在dbt セマンティックレイヤーはSnowflakeのみ対応していますが、今後BigQueryなど他のデータプラットフォームにも対応していくとのことです。
(ちなみに、dbt_metrics自体はBigQueryにも対応しています)

3. より最適化されたクエリ プランと SQL 生成

内部的に最適化されたSQLを生成してくれるようです。
もともとdbt_metricsではjinjaテンプレートを使って力技でメトリック定義をSQLに変換していましたが限界があったようです。(※1)
実際、dbt_metricsを使って複数のメトリクスを組み合わせたりすると、コンパイルされたSQLが複雑すぎてBigQueryの「too many subqueries or query is too complex.」エラーが出てつらいときがありました。

4. より複雑なメトリクス タイプ

dbt_metricsよりも使用できるメトリクスタイプが増えるようです。

他にもたくさん

ほかにも追加される or 追加される予定の機能がたくさんありますので、ぜひ元記事をチェックしてみてください。

MetricFlow触ってみた

前置きが長くなりましたが、実際にMetricFlowを動かしてみたいと思います。
MetricFlowの公式リポジトリを参考に進めていきます。
セットアップした後、用意されているtutorialを試します。

動作環境

Python 3.9.16
MetricFlow 0.140.0
pip 22.0.4
pipenv version 2023.5.19

セットアップ

Pythonやpipのインストールは割愛します。
(Metriflowの対応Pythonバージョンは<3.10なので注意)

MetricFlowのインストール

> pip install metricflow

MetricFlowのセットアップ

> mf setup

ようこそ画面がでて、どのDWH使うか聞いてきます。

🎉 Welcome to MetricFlow! 🎉

Please enter your data warehouse dialect.
Use 'duckdb' for a standalone demo.

Dialect (bigquery, databricks, duckdb, postgresql, redshift, snowflake):

duckdbを選べば、面倒なDWHのセットアップや認証を必要とせずローカルでデモを動かせるので今回はこれを選びます。

~/.metricflow/config.ymlが生成されます。

では、MetricFlowのチュートリアルを動かしてみましょう

MetricFlowのチュートリアルを試す

以下のコマンドを実行します。

> mf tutorial

するとヘルスチェックが実行されます。

❯ mf tutorial
For specifics on the health-checks, please visit https://docs.transform.co/docs/deployment/integrations/dw/
✔ Health checks completed.
• ✅ duckdbsqlclient - SELECT 1: Success!
• ✅ duckdbsqlclient - Create schema 'mf_demo': Success!
• ✅ duckdbsqlclient - Create table 'mf_demo.health_report' with a SELECT: Success!
• ✅ duckdbsqlclient - Drop table 'mf_demo.health_report': Success!
❓ Are the health-checks all passing? Please fix them before continuing [y/N]:

全部 ✅なら「y」で進みます。先に進むと、チュートリアル用のテーブルがduckdb内に生成され、MetrifFlowのチュートリアルを実行できるようになります。

補足:チュートリアル用のメトリクス定義とテーブル

チュートリアルで使われるメトリクスの定義ファイルは~/.metricflow/sample_modelsに格納されています。

❯ tree ~/.metricflow/sample_models
/Users/y-tsuzaki/.metricflow/sample_models
├── mf_demo_countries.yaml
├── mf_demo_customers.yaml
└── mf_demo_transactions.yaml

どのようなyamlファイルなのかは以下からご確認ください。 dbt_metricsとは異なる構文になっていることがわかります。

チュートリアルでは、countries, customers, transactionsの3つのテーブルを使います。


ここからは、MetricFlowの公式ドキュメントのチュートリアルを参考に進めます。

mf tutorialコマンドで表示されるサンプルコマンドと若干の違いがありますのでご注意ください。

メトリクスの一覧を見る

mf list-metricsコマンドを使います。

❯ mf list-metrics

メトリクスが一覧で表示されます。デモ用のメトリクスにはキャンセル数やキャンセル率、収益などのメトリクスを確認できます。

OUTPUT
✔ 🌱 We've found 13 metrics.
The list below shows metrics in the format of "metric_name: list of available dimensions"
• cancellations: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• cancellation_rate: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• revenue_usd: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• cancellations_mx: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• transaction_usd_na: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• transaction_usd_l7d_mx: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• transaction_usd_mtd: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• transaction_usd_na_l7d: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• transaction_amount_usd: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• transactions: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• quick_buy_amount_usd: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• quick_buy_transactions: customer__country__region, customer__ds, ds, is_large, quick_buy_transaction
• new_customers: country__region, ds

メトリックに含まれるディメンションを見る

mf list-dimensionsコマンドを使います。

❯ mf list-dimensions --metric-names new_customers
OUTPUT
✔ 🌱 We've found 2 common dimensions for metrics ['new_customers'].
• country__region
• ds

複数のメトリクスの中で使用可能な(=共通の)ディメンションを見る

--metric-namesに複数のメトリクスを指定します。

> mf list-dimensions --metric-names new_customers,transactions
OUTPUT
✔ 🌱 We've found 1 common dimensions for metrics ['new_customers', 'transactions'].
• ds

dsというディメンションが表示されました。先ほどはcountry__regionも表示されましたが、どちらのメトリクスでも共通で使えるのはディメンションはdsだけなので、dsのみ表示されます。

メトリクスをクエリする

mf queryでクエリすることができます

> mf query --metrics transactions --dimensions metric_time --order metric_time
OUTPUT
✔ Success 🦄 - query completed after 0.43 seconds
| metric_time         |   transactions |
|:--------------------|---------------:|
| 2022-03-07 00:00:00 |              2 |
| 2022-03-08 00:00:00 |              2 |
| 2022-03-09 00:00:00 |              1 |
| 2022-03-10 00:00:00 |              2 |
| 2022-03-11 00:00:00 |              1 |
| 2022-03-12 00:00:00 |              1 |
(略)

日毎のトランザクション数が表示されました。

SQLを見る

先ほどのコマンドに--explainを追加します

> mf query --metrics transactions --dimensions metric_time --order metric_time --explain
OUTPUT
✔ Success 🦄 - query completed after 0.30 seconds
🔎 SQL (remove --explain to see data or add --show-dataflow-plan to see the generated dataflow plan):
SELECT
  metric_time
  , SUM(transactions) AS transactions
FROM (
  SELECT
    ds AS metric_time
    , 1 AS transactions
  FROM mf_demo.mf_demo_transactions transactions_src_0
) subq_2
GROUP BY
  metric_time
ORDER BY metric_time

メトリックがどのようなSQLに変換されるのか確認することができます。

ディメンションによってメトリックをグループ化する

複数のディメンションを指定することができます。
今回はquick_buy_transactionというディメンションを追加しています。

❯ mf query --metrics transactions --dimensions metric_time,quick_buy_transaction --order metric_time
OUTPUT
✔ Success 🦄 - query completed after 0.39 seconds
| metric_time         | quick_buy_transaction   |   transactions |
|:--------------------|:------------------------|---------------:|
| 2022-03-07 00:00:00 | Quick Buy               |              1 |
| 2022-03-07 00:00:00 | Not Quick Buy           |              1 |
| 2022-03-08 00:00:00 | Quick Buy               |              1 |
| 2022-03-08 00:00:00 | Not Quick Buy           |              1 |
| 2022-03-09 00:00:00 | Not Quick Buy           |              1 |
(略)

日毎のトランザクション数をさらにquick_buy_transaction列で分割できています。

JOINが必要なディメンションの追加

多段的(multi-hop)なJOINが必要なディメンションも追加することができます。
以下の例ではcustomerテーブルに紐づくcountryテーブルのregionディメンションを追加しています。
ディメンションにはcustomer__country__regionのように__で連結した表現を使います。

> mf query --metrics transactions --dimensions metric_time,customer__country__region --order metric_time
OUTPUT
✔ Success 🦄 - query completed after 0.73 seconds
| metric_time         | customer__country__region   |   transactions |
|:--------------------|:----------------------------|---------------:|
| 2022-03-07 00:00:00 | EU                          |              1 |
| 2022-03-07 00:00:00 | NA                          |              1 |
| 2022-03-08 00:00:00 | NA                          |              2 |
| 2022-03-09 00:00:00 | NA                          |              1 |
| 2022-03-10 00:00:00 | NA                          |              2 |
| 2022-03-11 00:00:00 | NA                          |              1 |
(略)

週次の粒度で表示する

metric_timeディメンションをmetric_time__weekのように変更します。

mf query --metrics transactions --dimensions metric_time__week --order metric_time__week
OUTPUT
✔ Success 🦄 - query completed after 0.49 seconds
| metric_time__week   |   transactions |
|:--------------------|---------------:|
| 2022-03-07 00:00:00 |             10 |
| 2022-03-14 00:00:00 |              8 |
| 2022-03-21 00:00:00 |             15 |
| 2022-03-28 00:00:00 |             16 |
| 2022-04-04 00:00:00 |              1 |

週次で出ました。ポストフィックスで表現するのは直感的でいいですね。(?)

並び順を変える

--orderの値の前に-をつけます。
--order metric_time__week --order -metric_time__weekのように

> mf query --metrics transactions --dimensions metric_time__week --order -metric_time__week
OUTPUT
✔ Success 🦄 - query completed after 0.41 seconds
| metric_time__week   |   transactions |
|:--------------------|---------------:|
| 2022-04-04 00:00:00 |              1 |
| 2022-03-28 00:00:00 |             16 |
| 2022-03-21 00:00:00 |             15 |
| 2022-03-14 00:00:00 |              8 |
| 2022-03-07 00:00:00 |             10 |

ね、簡単でしょう。

より複雑な累積とフィルターを使ったメトリック

transaction_usd_na_l7dというメトリックを使います。
このメトリックでは、地域がNAであるトランザクションの金額について7日間の累計を計算しています。

> mf query --metrics transaction_usd_na_l7d --dimensions metric_time --order metric_time
OUTPUT
✔ Success 🦄 - query completed after 0.56 seconds
| metric_time         |   transaction_usd_na_l7d |
|:--------------------|-------------------------:|
| 2022-03-07 00:00:00 |                   295.03 |
| 2022-03-08 00:00:00 |                   872.03 |
| 2022-03-09 00:00:00 |                   879.69 |
| 2022-03-10 00:00:00 |                  1051.12 |
| 2022-03-11 00:00:00 |                  1259.49 |
(略)

ちなみにtransaction_usd_na_l7dというメトリックは以下のように定義されています。

mf_demo_transactions.yaml
metric:
  name: transaction_usd_na_l7d
  owners:
    - support@transformdata.io
  type: cumulative
  type_params:
    measures:
      - transaction_amount_usd
    window: 7 days
  constraint: |
    customer__country__region = 'NA'

どのようなSQLになっているか気になる人は--explainをつけてみてみましょう。(割愛)

複数のメトリクスとwhereを試す

--whereを追加することで絞り込みをすることができます。

> mf query --metrics transactions,transaction_usd_na,transaction_usd_na_l7d --dimensions metric_time,is_large --order metric_time --where "metric_time between '2022-03-20' and '2022-04-01'"
✔ Success 🦄 - query completed after 0.88 seconds
| metric_time         | is_large   |   transactions |   transaction_usd_na |   transaction_usd_na_l7d |
|:--------------------|:-----------|---------------:|---------------------:|-------------------------:|
| 2022-03-20 00:00:00 | True       |         nan    |               nan    |                  1405.94 |
| 2022-03-21 00:00:00 | True       |           3.00 |               639.87 |                  1866.47 |
| 2022-03-22 00:00:00 | True       |           3.00 |               522.68 |                  2122.40 |
| 2022-03-23 00:00:00 | True       |           2.00 |               215.14 |                  2064.38 |
(略)

チュートリアル用のデータを削除する

以下のコマンドでチュートリアル用のテーブルを削除できます。

> mf tutorial --skip-dw --drop-tables

まとめ

dbt セマンティックレイヤーの新しいパッケージとなるMetricFlowについて、公式のチュートリアルをやってみました。
チュートリアルを通してMetricFlowがどのようなものなのか雰囲気が少しわかったような気がします。
PowerBIやTableauのような高性能なBIツールを使ったことがないので、それらと比べてMetrifFlowのメトリック機能が足りているか判断できませんが、結構柔軟にメトリックの計算ができそうだなと感じています。
今回はYamlファイルの内容や記述ルールについて触れられなかったので、また別の機会に深掘りしたいと思います。

少しでも参考になりましましたら、「いいね」「Twitterシェア」をいただけたら嬉しいです🤝

12
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?