dbt platform で Saved Query の出力先データベースの制御方法を確認してみる
はじめに
dbt の Saved Query には出力スキーマを制御するオプションが提供されていますが、データベースを指定するオプションがありません。
エクスポート先のデータベースはどのように制御できるか確認した際の内容を記事としました。
先に結論ですが、Saved Query のエクスポート先データベースは models 側の+database設定からは制御できず、target.databaseが使われます。
そのため、エクスポート先のデータベースを切り替えたい場合は、開発環境ではユーザー単位のクレデンシャル、デプロイメント環境では Connection overrides で target.database を上書きする必要があります。
Saved Query と export の概要
Saved Query は、セマンティックレイヤーで定義したメトリクスやディメンションを使った定型クエリをあらかじめ定義しておく仕組みです。
あわせて、exports を定義することで、Saved Query の結果を DWH 上のテーブル・ビューとして物理化できます。
本機能については以下に記載があります。
特に出力先スキーマを切り替えについて、exports.config.schemaで出力先スキーマを変更できます。
特徴として、通常の dbt モデルと Saved Query(Export)ではカスタムスキーマの解決方法が以下の通り異なります。
- dbt モデルでのデフォルトルール
- {{ default_schema }}_{{ custom_schema_name }}
- Saved queries
- schema で指定した名前がそのまま使用される
データベースの出力制御については特に明記されていないので、以降で確認してみます。
その他、本機能の概要は以下もご参照ください。
前提条件
検証環境
以下の環境を使用しています。
- dbt
- dbt platform
- 開発環境、デプロイメント環境いずれも Fusion Stable リリーストラック
- DWH:Snowflake
また、この記事では dbt Fusion エンジンおよび dbt platform Latest リリーストラックで利用可能な新しい YAML 記法(モデルの columns 配下にセマンティックモデル定義を記述する形式)を使用しています。
事前準備
検証用のプロジェクトでは、models/ 配下を 2 レイヤーに分け、それぞれ環境別に異なるデータベースに出力する設定としています。その他、カスタムスキーマ設定も追加しています。
| レイヤー | ディレクトリ | prd 出力先 | dev 出力先 |
|---|---|---|---|
| staging | models/staging/ |
stg_db |
dev_stg_db |
| mart | models/mart/ |
mart_db |
dev_mart_db |
models:
my_new_project:
+materialized: table
staging:
+materialized: view
+schema: jaffle_shop
+database: |
{%- if target.name == "prd" -%} stg_db
{%- elif target.name == "dev" -%} dev_stg_db
{%- else -%} invalid_database
{%- endif -%}
mart:
+materialized: table
+schema: jaffle_shop
+database: |
{%- if target.name == "prd" -%} mart_db
{%- elif target.name == "dev" -%} dev_mart_db
{%- else -%} invalid_database
{%- endif -%}
ファイル配置は以下の通りです。
models/
├── schema.yml
├── sources/
├── staging/
│ ├── stg_customers.sql
│ └── stg_orders.sql
└── mart/
├── customers.sql
├── customers.yml # セマンティックモデル + saved_query
├── time_spine_daily.sql
└── time_spine_daily.yml
また、必要な Snowflake オブジェクトとして、STG_DB / DEV_STG_DB / MART_DB / DEV_MART_DB の他、プロジェクトのデフォルト出力先としてANALYTICSの5つのデータベースを用意しておきました。
セマンティックモデルと Saved Query は models/mart/customers.yml に以下のように定義しています。
version: 2
models:
- name: customers
semantic_model:
enabled: true
agg_time_dimension: first_order_date
columns:
- name: customer_id
data_tests:
- unique
- not_null
entity:
type: primary
name: customer
- name: first_order_date
granularity: day
dimension:
type: time
- name: most_recent_order_date
granularity: day
dimension:
type: time
- name: number_of_orders
metrics:
- name: customer_count
type: simple
label: Customer Count
agg: count
expr: customer_id
- name: total_orders
type: simple
label: Total Orders
agg: sum
expr: number_of_orders
saved_queries:
- name: sq_customer_summary
description: Monthly customer count and order totals by first order date
query_params:
metrics:
- customer_count
- total_orders
group_by:
- "TimeDimension('customer__first_order_date', 'month')"
exports:
- name: sq_customer_summary_export
config:
export_as: table
リネージは以下のようになります。

デフォルト設定での出力先
事前準備の状態で Saved Query を export して出力先データベースを確認します。
開発環境
Studio IDE で Saved Query を export してみます。
dbt build --select saved_query:sq_customer_summary
実行後の出力先は以下となりました。
ANALYTICS / DBT_TYASUHARA / SQ_CUSTOMER_SUMMARY_EXPORT
プロジェクトの設定は以下の通りです。
- コネクション(PJ の最終的なデフォルト)

- Development Credential
- 特に指定なし
- コネクションのデフォルトが使われる

IDE 上でもtargetの値を以下のように確認できます。
> dbt show --inline "select '{{ target.name }}' as target_name,
'{{ target.database }}' as database, '{{ target.schema }}'
as schema, '{{ target.warehouse }}' as warehouse, '{{
target.role }}' as role"
┌─────────────┬───────────┬───────────────┬────────────┬──────┐
│ TARGET_NAME ┆ DATABASE ┆ SCHEMA ┆ WAREHOUSE ┆ ROLE │
╞═════════════╪═══════════╪═══════════════╪════════════╪══════╡
│ dev ┆ ANALYTICS ┆ dbt_tyasuhara ┆ compute_wh ┆ None │
└─────────────┴───────────┴───────────────┴────────────┴──────┘
開発環境では、プロジェクト(コネクション)に設定したデフォルトデータベースがtarget.databaseとして使われ、それがそのまま export 先になっていることが分かります。
デプロイメント環境
同じ Saved Query をデプロイメント環境のジョブで実行すると、以下の出力先となりました。
ANALYTICS / PRD / SQ_CUSTOMER_SUMMARY_EXPORT
本番環境のプロファイルは以下の設定です。
- Database:指定なし
- Schema:
prd


デプロイメント環境ではコネクションで指定されたデータベースと、環境のデフォルトスキーマが組み合わさって出力先となります。
開発環境・デプロイメント環境の実際の出力は下図のようになりました。

その他のモデルはカスタムデータベース・スキーマの設定に基づいて指定のデータベース・スキーマへ出力されますが、Saved Query の export 先はこの指定とは異なる挙動になることが分かります。
開発環境のモデル出力一覧:

デプロイメント環境のモデル出力一覧:

export に schema を追加する
Saved Query 側の export config でschemaを指定してみます。
saved_queries:
- name: sq_customer_summary
description: Monthly customer count and order totals by first order date
query_params:
metrics:
- customer_count
- total_orders
group_by:
- "TimeDimension('customer__first_order_date', 'month')"
exports:
- name: sq_customer_summary_export
config:
export_as: table
schema: sq_customer_summary
この状態で再度 dbt build を実行します。
dbt build --select saved_query:sq_customer_summary
開発環境とデプロイメント環境、それぞれの出力先は以下のようになりました。
開発環境:
ANALYTICS / SQ_CUSTOMER_SUMMARY / SQ_CUSTOMER_SUMMARY_EXPORT
デプロイメント環境:
ANALYTICS / SQ_CUSTOMER_SUMMARY / SQ_CUSTOMER_SUMMARY_EXPORT
config 内のschema指定が両環境ともに反映され、同じデータベース・スキーマへ出力されています。
ターゲットのデータベースが同じ場合、開発と本番で出力先を分けるには Jinja 記法などで制御する必要があることが分かります。

export の database を制御する
export config 側に database を指定するオプションは確認できませんでした。実際に指定するとエラーとなります。

このため、別の方法として開発環境ではユーザー単位のクレデンシャルでデータベースを上書きします。

IDE 上でtargetの値を確認すると、target.databaseが上書きされていることが分かります。
> dbt show --inline "select '{{ target.name }}' as target_name,
'{{ target.database }}' as database, '{{ target.schema }}'
as schema, '{{ target.warehouse }}' as warehouse, '{{
target.role }}' as role"
┌─────────────┬─────────────┬───────────────┬────────────┬──────┐
│ TARGET_NAME ┆ DATABASE ┆ SCHEMA ┆ WAREHOUSE ┆ ROLE │
╞═════════════╪═════════════╪═══════════════╪════════════╪══════╡
│ dev ┆ dev_mart_db ┆ dbt_tyasuhara ┆ compute_wh ┆ None │
└─────────────┴─────────────┴───────────────┴────────────┴──────┘
この状態で開発環境で dbt build を実行します。
dbt build --select saved_query:sq_customer_summary
出力先は以下となり、上書きしたデータベースが反映されていることが確認できます。
DEV_MART_DB / SQ_CUSTOMER_SUMMARY / SQ_CUSTOMER_SUMMARY_EXPORT

同様にデプロイメント環境でも上書きを行います。
デプロイメント環境では「Profile details > Connection overrides」から、環境ごとの接続情報を上書きできます。

この設定でジョブを実行すると、以下の出力先となりました。
MART_DB / SQ_CUSTOMER_SUMMARY / SQ_CUSTOMER_SUMMARY_EXPORT

まとめ
試してみた内容から、以下のように整理できます。
- models 側の
+databaseを環境別に分岐させる従来パターンは、Saved Query の export には伝播しない - export config の
schema指定でスキーマ単位での住み分けは可能 - データベースは export config 側からは指定できないため、コネクションのデフォルト、もしくはユーザークレデンシャル / Connection overrides による上書きで制御する必要がある
- モデルはカスタムデータベースで制御しつつ、Saved Query はプロジェクトのデフォルトを使うなど、運用上の取り決めが必要になる
さいごに
dbt Saved Query の export 出力先(データベース・スキーマ)について、各種設定がどのように反映されるかを確認してみました。
こちらの内容がどなたかの参考になれば幸いです。







