🌠

dbtのディレクトリをそのままDWH上にも表現したい

2022/09/11に公開

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つのスキーマ名を変更する方法が記されています。

  1. 各SQL内でconfigの設定を行います
{{ config(schema='marketing') }}

select ...

1を実行してみると(実行したクエリは以下のものです)、画像のようにスキーマが作成されていました!configがうまく反映されている模様です。

{{ config(schema='marketing') }}

select * from {{ source('XXX', 'XXX') }}

  1. 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