dbt platform で Saved Query の Export を試してみた
はじめに
dbt platform の Saved Query を試してみたので、その内容を記事としました。
Saved Query
dbt Semantic Layer では、よく使うクエリパターンを Saved Query として YAML に定義しておくことができます。定義した Saved Query には Export を設定することで、集計済みの結果をテーブルやビューとして DWH に書き出すことができます。セマンティックレイヤーの API にネイティブ対応していない BI ツール向けのオプションとして提供されています。
この場合、BI ツールからの参照経路は以下の通りです。
BI ツール / SQL クライアント
└─ SELECT * FROM export_table ← テーブルを直接参照(SL を経由しない)
なお、多数のテーブルから選ぶのが難しい・ユーザーが集計やフィルタを誤るリスクがある場合など、精度が求められるケースでは通常のセマンティックモデルを介する接続が推奨されています。
Saved Query / Export については以下に記載があります。
以降で、各種設定を見ていきます。
前提条件
検証環境
以下の環境を使用しています。
- DWH:Snowflake
- 検証用データ:
SNOWFLAKE_SAMPLE_DATA.TPCH_SF10
- 検証用データ:
- dbt platform
- BI ツール
- Tableau Desktop:2026.1
サンプルデータは以下を使用します。
| テーブル | 行数 |
|---|---|
TPCH_SF10.ORDERS |
15,000,000 |
事前準備
検証用プロジェクトに以下のファイルを用意しました。
dbt-sl-test/models/
├── tpch_sources.yml # SNOWFLAKE_SAMPLE_DATA.TPCH_SF10 ソース定義
├── stg_tpch_orders.sql # ORDERS 薄いリネーム層(VIEW)
├── stg_tpch_orders.yml # セマンティックモデル + メトリクス
各種定義は以下の通りです。
version: 2
sources:
- name: tpch
description: Snowflake サンプルデータ TPC-H SF10(スケールファクタ10、約1,500万注文)
database: snowflake_sample_data
schema: tpch_sf10
tables:
- name: orders
description: 注文ヘッダー。1行=1注文(15,000,000行)
- name: lineitem
description: 注文明細。1行=1注文明細(59,986,052行)
dbt モデル定義:
{{ config(materialized='view') }}
SELECT
o_orderkey AS order_key,
o_custkey AS customer_key,
o_orderstatus AS order_status,
o_totalprice AS total_price,
o_orderdate AS order_date,
o_orderpriority AS order_priority
FROM {{ source('tpch', 'orders') }}
セマンティックモデル定義:
version: 2
models:
- name: stg_tpch_orders
semantic_model:
enabled: true
agg_time_dimension: order_date
columns:
- name: order_key
entity:
type: primary
name: tpch_order
- name: customer_key
entity:
type: foreign
name: tpch_customer
- name: order_date
granularity: day
dimension:
type: time
- name: order_status
dimension:
type: categorical # F=完了 / O=処理中 / P=一部出荷
- name: order_priority
dimension:
type: categorical # 1-URGENT / 2-HIGH / 3-MEDIUM / 4-NOT SPECIFIED / 5-LOW
metrics:
- name: tpch_order_count
type: simple
label: 注文数(TPC-H)
agg: count
expr: 1
- name: tpch_total_revenue
type: simple
label: 総売上(TPC-H)
agg: sum
expr: total_price
Saved Query と Export の定義
Saved Query は saved_queries ブロックで YAML に定義します。exports を設定することで、dbt sl export コマンドで集計済みテーブルを DWH に書き出すことができます。
ここでは、ステータス・優先度・月別の注文数と売上を集計する Saved Query を定義して Export を実行します。
定義(saved_queries_tpch.yml)
saved_queries:
- name: tpch_orders_by_status
description: "ステータス×優先度×月別の注文数・売上(TPC-H)"
label: "TPC-H 注文サマリー"
query_params:
metrics:
- tpch_order_count
- tpch_total_revenue
group_by:
- "Dimension('tpch_order__order_status')"
- "Dimension('tpch_order__order_priority')"
- "TimeDimension('metric_time', 'month')"
exports:
- name: tpch_orders_by_status_tbl
config:
export_as: table
開発環境での Export を実行します。特に指定がない場合の出力先スキーマはデフォルトスキーマです。
$ dbt parse
$ dbt sl export --saved-query tpch_orders_by_status
- Created TABLE at `dbt_tyasuhara.tpch_orders_by_status_tbl`
実行時には以下の SQL が発行されていました。
CREATE OR REPLACE TABLE dbt_tyasuhara.tpch_orders_by_status_tbl AS (
SELECT
metric_time__month,
tpch_order__order_status,
tpch_order__order_priority,
SUM(__tpch_order_count) AS tpch_order_count,
SUM(__tpch_total_revenue) AS tpch_total_revenue
FROM (
SELECT
DATE_TRUNC('month', order_date) AS metric_time__month,
order_status AS tpch_order__order_status,
order_priority AS tpch_order__order_priority,
1 AS __tpch_order_count,
total_price AS __tpch_total_revenue
FROM dbt_sl_db.dbt_tyasuhara.stg_tpch_orders stg_tpch_orders_src_10000
) subq_3
GROUP BY metric_time__month, tpch_order__order_status, tpch_order__order_priority
)
Export されたテーブルを確認します。YAML の定義し従い、集計済みテーブルとして作成されています。
-- 元データ: 15,000,000 行
SELECT COUNT(*) AS src_rows FROM SNOWFLAKE_SAMPLE_DATA.TPCH_SF10.ORDERS;
+----------+
| SRC_ROWS |
+----------+
| 15000000 |
+----------+
-- export テーブル: 450 行(status 3 × priority 5 × 月 30 ≒ 450)
SELECT COUNT(*) AS export_rows
FROM DBT_SL_DB.DBT_TYASUHARA.tpch_orders_by_status_tbl;
+-------------+
| EXPORT_ROWS |
+-------------+
| 450 |
+-------------+
BI ツール(Tableau)から export テーブルを直接参照した場合も、通常のようにクエリした場合と同じ結果となります。


本番環境での Export 実行
開発環境との違い
開発環境では dbt sl export --saved-query を使いますが、本番環境(dbt platform のジョブ)では dbt build を使います。
環境変数の設定
ジョブ経由で Saved Query を作成する場合は dbt platform の Environment variables にDBT_ENGINE_EXPORT_SAVED_QUERIES = TRUEの設定が必要です。

この設定により、dbt build 実行時に Saved Query も自動的に処理されます。Export は元モデルが最新になった後に動くため、データの鮮度が保たれます。
ジョブを実行すると本番環境のデフォルトスキーマに出力されます。
リネージ図では Saved Query セマンティックモデルの下流に位置していることが確認できます。

Export のカスタムスキーマ
通常の Export(cache: false)では exports.config.schema で出力先スキーマを変更できます。
以下のようにカスタムスキーマを設定してみます。
exports:
- name: tpch_orders_by_status_tbl
config:
export_as: table
schema: tpch_exports # デフォルトスキーマとは別のスキーマに出力
この状態で開発環境で実行すると、デフォルトスキーマ(dbt_tyasuhara)ではなく、指定した tpch_exports スキーマにテーブルが作成されます。
$ dbt sl export --saved-query tpch_orders_by_status
- Created TABLE at `tpch_exports.tpch_orders_by_status_tbl`
ジョブ(本番環境)経由でも同じ tpch_exports スキーマに出力されました。

モデルと Saved Query のスキーマ解決
モデルと Saved Query(Export)ではカスタムスキーマの解決方法が異なりました。
検証結果とあわせて以下を参照すると、モデルでのデフォルトルールでは{{ target.schema }}_{{ schema }}ですが、Saved queries では指定した名前がそのまま使用されるようです。
そのため、開発・本番環境ともに同じスキーマ名が使われる点に注意が必要です。
環境ごとに出力先スキーマを切り替え
環境ごとに出力先スキーマを切り替えたい場合は、以下のように Jinja 式で分岐させることができます。
exports:
- name: tpch_orders_by_status_tbl
config:
export_as: table
schema: "{{ 'tpch_exports' if target.name == 'prd' else target.schema ~ '_tpch_exports' }}"
この場合、それぞれ下図の通り出力できました。
開発環境:

本番環境:

Declarative caching
Enterprise 以上のプランでは Export 時に cache: enabled: true を追加設定することで、Declarative caching を有効化できます。
有効化すると、dbt セマンティックレイヤー参照時に、処理に応じて自動でキャッシュテーブルを参照するように構成できます。
設定
既存の Saved Query 定義に config.cache.enabled: true を追加します。
saved_queries:
- name: tpch_orders_by_status
description: "ステータス×優先度×月別の注文数・売上(TPC-H)"
label: "TPC-H 注文サマリー"
config:
cache:
enabled: true # ← 追加
query_params:
metrics:
- tpch_order_count
- tpch_total_revenue
group_by:
- "Dimension('tpch_order__order_status')"
- "Dimension('tpch_order__order_priority')"
- "TimeDimension('metric_time', 'month')"
exports:
- name: tpch_orders_by_status_tbl
config:
export_as: table
Export の実行
開発環境でのコマンドは通常の Export と同様です。
dbt parse
dbt sl export --saved-query tpch_orders_by_status
Export テーブルの内容・行数も cache: enabled なしの場合と同一です。
cache: enabled: true 時の出力先スキーマ
開発環境(dbt sl export)では、cache.enabled: true を設定しても 通常の export と同じデフォルトスキーマに出力されます。
デプロイメント環境では dbt_sl_cache という専用のスキーマがキャッシュテーブルの作成先となります。テーブル名は Saved Query 名ではなく、dbt によって内部的に生成される名称となっていました。

さいごに
dbt Semantic Layer の Saved Query と Export 機能、および Declarative caching の設定を確認してみました。
こちらの内容がどなたかの参考になれば幸いです。









