dbtのtargetに合わせて接続先を変更する on Snowflake
背景
dbtでは接続先のDBやスキーマ名を動的に変えたい場合があります。
例えば、rawディレクトリ以下のモデルはrawデータベースに、martディレクトリ以下のモデルはmartデータベースに成果物を作成するなど。また、ユーザー1さんの開発時にはmart_user1データベースに、プロダクションのデプロイ時にはmartデータベースにモデルを作成するなど。
整理すると2つの考慮事項があります。
①モデル管理階層:rawディレクトリ配下 or martディレクトリ配下のモデル化
②開発プロセス:開発時 or デプロイ時
本記事では、以下のようなモデルを管理している際に、
以下のような結果を得ることを目的とします。モデル階層と開発・プロダクション環境に応じてDBとSCHEMAの作成先を変更します。
# ユーザー1の開発時
- raw_user1
- public
- raw_model1
- system1
- system1_model
- system2
- system2_model
- mart_user1
- public
- model1
# デプロイ時
- raw
- public
- raw_model1
- system1
- system1_model
- system2
- system2_model
- mart
- public
- model1
以下、どのように接続先を変更するかまとめます。尚、検証はSnowflakeで行っています。
設定
モデル管理階層に応じたDB名の設定
dbt_project.yml
に以下のような記述をすることで、ディレクトリ配下のモデルに対して、どのDBとSCHEMAにモデルを作成するか指定することができます。
models:
my_new_project:
raw: # model配下のディレクトリを指定
+database: raw
+schema: public
system1: # サブディレクトリを指定
+schema: system1
system2:
+schema: system2
mart:
+database: mart
+schema: public
target.nameに応じたDBとSCHEMA名のカスタマイズ
target.nameの設定
dbt cloudでは profile settings > Credentials > target.name に、開発者固有の成果物の作成先の名称を指定できます。ここでは dev
を指定します。dbt coreでもどこかしらに同様の設定が可能なはずです。続いて、プロダクションのデプロイジョブに対しては target nameにprod
を指定します。
上記のプロパティはjinjaマクロ中でtarget.name
として取得可能です(参照)。
target.db/schemaの設定
target.nameと同様に、profile settings > Credentials のDBとSchemaに、開発者固有のDBとSCHEMA名を指定します。ここではどちらもuser1
を指定します。
上記のプロパティはjinjaマクロ中でtarget.database
およびtarget.schema
として取得可能です。
マクロの作成
dbt標準マクロとしてgenerate_database_nameとgenerate_schema_nameがあり、名前の通りDB名やスキーマ名を解決する役割を担っています。
このマクロは上書きしてカスタマイズすることができ、target.nameにより処理を分岐させることで、開発デプロイ時とプロダクションのデプロイ時で解決するDB・スキーマ名を変更することが可能です。こちらのコミュニティスレッドでも紹介されている手法です。
今回は以下のようなマクロをmacroディレクトリ配下に作成(=上書き)しています。
# macro/generate_database_name.sql
{% macro generate_database_name(custom_database_name=none, node=none) -%}
{%- if custom_database_name is none -%}
{{ exceptions.raise_compiler_error("custome database must be specified in dbt_project.yml") }}
{%- endif -%}
{%- if target.name == 'prod' -%}
{{ custom_database_name }}
{%- else -%}
{%- if target.database is none -%}
{{ exceptions.raise_compiler_error("target.database must be specified in a development environment") }}
{%- else -%}
{{ custom_database_name | trim }}_{{ target.database | trim }}
{%- endif -%}
{%- endif -%}
{%- endmacro %}
# generate_schema_name.sql
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- if target.name == 'prod' -%}
{{ custom_schema_name }}
{%- else -%}
{{ custom_schema_name | trim }}_{{ target.schema | trim }}
{%- endif -%}
{%- endmacro %}
custom_database/schema_nameが引数に指定されていますが、これはdbt_project.yml
で指定したDB名やスキーマ名が与えられます。
マクロの詳細な説明は省きますが、以下のような実装をしています。
- target.nameがprodの場合、custom_database/schema_nameを成果物の作成先として指定
- target.nameがprod以外の場合、custom_database_target.database、custom_schema_target.schemaを作成先と指定
まとめ
dbt_project.ymlと各種targetプロパティの設定、そしてDB・Schema名を解決するマクロのカスタマイズにより、状況とモデル管理階層に応じた成果物の作成先を指定することが可能になりました。
Discussion