dbt platform で Saved Query の Export を試してみた

dbt platform で Saved Query の Export を試してみた

2026.04.17

はじめに

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 については以下に記載があります。

https://docs.getdbt.com/docs/build/saved-queries?version=1.12

https://docs.getdbt.com/docs/use-dbt-semantic-layer/exports?version=1.12

以降で、各種設定を見ていきます。

前提条件

検証環境

以下の環境を使用しています。

  • 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      # セマンティックモデル + メトリクス

各種定義は以下の通りです。

tpch_sources.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 モデル定義:

stg_tpch_orders.sql
{{ 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') }}

セマンティックモデル定義:

stg_tpch_orders.yml
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_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 テーブルを直接参照した場合も、通常のようにクエリした場合と同じ結果となります。

image

image

本番環境での Export 実行

開発環境との違い

開発環境では dbt sl export --saved-query を使いますが、本番環境(dbt platform のジョブ)では dbt build を使います。

環境変数の設定

ジョブ経由で Saved Query を作成する場合は dbt platform の Environment variables にDBT_ENGINE_EXPORT_SAVED_QUERIES = TRUEの設定が必要です。

image

この設定により、dbt build 実行時に Saved Query も自動的に処理されます。Export は元モデルが最新になった後に動くため、データの鮮度が保たれます。

ジョブを実行すると本番環境のデフォルトスキーマに出力されます。

リネージ図では Saved Query セマンティックモデルの下流に位置していることが確認できます。

image

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 スキーマに出力されました。

image

モデルと Saved Query のスキーマ解決

モデルと Saved Query(Export)ではカスタムスキーマの解決方法が異なりました。
検証結果とあわせて以下を参照すると、モデルでのデフォルトルールでは{{ target.schema }}_{{ schema }}ですが、Saved queries では指定した名前がそのまま使用されるようです。

https://docs.getdbt.com/reference/resource-configs/schema

そのため、開発・本番環境ともに同じスキーマ名が使われる点に注意が必要です。

環境ごとに出力先スキーマを切り替え

環境ごとに出力先スキーマを切り替えたい場合は、以下のように Jinja 式で分岐させることができます。

exports:
  - name: tpch_orders_by_status_tbl
    config:
      export_as: table
      schema: "{{ 'tpch_exports' if target.name == 'prd' else target.schema ~ '_tpch_exports' }}"

この場合、それぞれ下図の通り出力できました。

開発環境:

image

本番環境:

image

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 によって内部的に生成される名称となっていました。

image

https://docs.getdbt.com/docs/use-dbt-semantic-layer/sl-cache

さいごに

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

この記事をシェアする

関連記事