dbtのディレクトリをそのままDWH上にも表現したい
dbtのディレクトリをそのままDWH上にも表現したい
最近dbtを使い始めたものです。dbtが色々便利すぎて感動していますが、1つ不便に感じたことがありました。dbt run
を実行した際にスキーマ名が最初に設定したしたものに決まてしまっていることに。。。
ということで今回はスキーマ名をいかに自分好みにカスタマイズするかについて考えてみたいと思います。ご指摘などあれば教えていただければと思います!
普通にリリースをしてみる編
とりあえず、dbt内で簡単なSQLを書いてみます。
-- models/aaa.sql
select * from {{ source('XXX', 'XXX') }}
上記を実行してみます。すると以下のようにビューが作成されました。
DBT_DHARATO
とは何かというと、Snowflakeへの接続設定時に指定したスキーマ名になります(一番下のschema
欄)。ただこのままだとスキーマ名が初期に指定したものしか使えなくなってしまいます....
公式ドキュメント編
そこで参考にしたのが公式ドキュメントです(Using custom schemas)
ここではまず2つのスキーマ名を変更する方法が記されています。
- 各SQL内で
config
の設定を行います
{{ config(schema='marketing') }}
select ...
1を実行してみると(実行したクエリは以下のものです)、画像のようにスキーマが作成されていました!config
がうまく反映されている模様です。
{{ config(schema='marketing') }}
select * from {{ source('XXX', 'XXX') }}
-
dbt_project.yml
でスキーマ名の指定を行います。
models:
my_project:
marketing:
+schema: marketing
こちらも同様にスキーマが作成されていることが確認できますね。
1の場合、各SQLファイルごとにconfig
を作成しなければならず運用のことを鑑みても大変な気がします(スキーマ名変更時すべてのSQLファイルを修正する必要があるため)。そのため実際に使用するなら2のdbt_project.yml
かなと考えています。なんといってもスキーマごとに命名を管理できるため!
ここで思ったことですが、DBT_DHARATO
という名前が邪魔だなと。。どうにかして取りたいなと思ってしまいました。ただこれはdbt側の配慮でもあり、全員が同一のスキーマ名を使用するとdbt run
を実行する毎にデグレってしまうことがあります。よってローカルで開発を行う際はDBT_<個人名>_<スキーマ名>
の方が良いのかもしれません。ただ今、私は<スキーマ名>
が欲しいのです。。。
続・公式ドキュメント編
さらに公式ドキュメントを読み進めていきます。どうやらmacros
フォルダ配下でgenerate_schema_name.sql
の中をいじることでスキーマ名を設定することができそうです。また設定時、jinja
を使用するとさらに設定の幅が広がりそうです。
generate_schema_name
で使用できるjinjaのコンテクスト一覧
Jinja context | type | Available |
---|---|---|
target | Variable | ✅ |
env_var | Variable | ✅ |
var | Variable | Limited |
exceptions | Macro | ✅ |
log | Macro | ✅ |
Other macros in your project | Macro | ✅ |
Other macros in your packages | Macro | ✅ |
macors/generate_schema_name.sql
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- set default_schema = target.schema -%}
{%- if custom_schema_name is none -%}
{{ default_schema }}
{%- else -%}
{{ default_schema }}_{{ custom_schema_name | trim }}
{%- endif -%}
{%- endmacro %}
処理の詳細の説明割愛しますが、いい感じにスキーマが作成されていることが確認できました。
-
{{ default_schema }}
あらかじめ設定しているスキーマ名(例:DBT_DHARATO
) -
{{ custom_schema_name | trim }}
dbt_project.yml
や各SQLファイルで指定しているconfig
のスキーマ名
つまり先ほどの疑問 私は<スキーマ名>が欲しいのです
の答えですが、custom_schema_name
さえ設定しているならば、以下のクエリをmacros
配下のフォルダに設定すれば想定通りのスキーマ名を作成できるはずです。
macors/generate_schema_name.sql
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- set default_schema = target.schema -%}
{%- if custom_schema_name is none -%}
{{ default_schema }}
{%- else -%}
{{ custom_schema_name | trim }}
{%- endif -%}
{%- endmacro %}
ディレクトリの名前をそのままスキーマ名にしたい
上で説明したことを利用すれば、dbt_project.yml
や各SQLファイルで指定しているconfig
のスキーマ名を指定すればスキーマ名をカスタマイズできることが分かりました。ただまた私は思ってしまったのです。ディレクトリ構造をそのままスキーマ名として利用したいと。。。それができればなんか分かりやすそうだなと。。。
そこで、下記のようなディレクトリ構造をdbt上で想定します。
DB名
├ staging
├ intermediate
├ information
この構造をDWH上で表現するためには先ほど示したようにdbt_project.yml
や各SQLファイル内で設定する方法があります。ただフォルダ名を変更した際、再度設定しなおす必要があると思われます。そのため設定漏れなどが生じるかもと素人ながら思いました。
よってまた異なるmacros
を使用する必要があると思いました。そこで参考にしたのがDBT custom schema using folder structureです。
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- set default_schema = target.schema -%}
{%- if custom_schema_name is none -%}
{# Check if the model does not contain a subfolder (e.g, models created at the MODELS root folder) #}
{% if node.fqn[1:-1]|length == 0 %}
{{ default_schema }}
{% else %}
{# Concat the subfolder(s) name #}
{% set prefix = node.fqn[1:-1]|join('_') %}
{{ prefix | trim }}
{% endif %}
{%- else -%}
{{ default_schema }}_{{ custom_schema_name | trim }}
{%- endif -%}
{%- endmacro %}
先ほどに続き処理内容の説明は割愛します。上記を実行した結果が以下の画像になりました。(他のスキーマもあり分かりにくいと思いますがすみません。。。)無事に狙ったスキーマ名がDWH上にも反映されていることが確認できました。
さいごに
これまでの過程を踏まえて、Jinjaは可能性が大きいなとぼんやり思いました。dbtについてこれからも調べ続けていく所存です。今後とも宜しくお願いします。
Discussion