はじめに
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に対応
メトリクスの計算に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
メトリクスが一覧で表示されます。デモ用のメトリクスにはキャンセル数やキャンセル率、収益などのメトリクスを確認できます。
✔ 🌱 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
✔ 🌱 We've found 2 common dimensions for metrics ['new_customers'].
• country__region
• ds
複数のメトリクスの中で使用可能な(=共通の)ディメンションを見る
--metric-names
に複数のメトリクスを指定します。
> mf list-dimensions --metric-names new_customers,transactions
✔ 🌱 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
✔ 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
✔ 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
✔ 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
✔ 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
✔ 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
✔ 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
✔ 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
というメトリックは以下のように定義されています。
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シェア」をいただけたら嬉しいです🤝
記事を投稿しました! dbtの新しいセマンティックレイヤー「MetricFlow」を触ってみた [データ分析] on #Qiita https://t.co/Q4sI347rai
— つざき@データエンジニア入門中 (@820zacky) May 26, 2023