dbt Model Versions について調べてみました

2024-12-06

こんにちは。株式会社 Belong にて Data Platform チームに所属する Shuhei です。

弊社は dbt-core を用いて BigQuery にてデータ分析基盤を構築しています。

先日、dbt Model Versions を試す機会があったため、その機能や使い方、ハマったエラーなどをご紹介します。

dbt Model Versions とは

dbt Model Vesions により、dbt モデルのバージョン管理ができるようになります。

https://docs.getdbt.com/docs/collaborate/govern/model-versions

例えば、ある dbt モデルに対して大きな変更を加える場合、参照関係にある後続のモデルやデータ利用者への影響が懸念されることがあるかと思います。

このとき、dbt Model Versions を使ってモデルのバージョン管理ができれば、「旧バージョンと新バージョンを共存させた並行稼働期間を設け、段階的に新バージョンへ移行する」などといったことがやりやすくなります。

dbt Model Versions の使い方

dbt Model Versions は下記 3 種のファイルを編集することで使用することができます。

  1. バージョン管理をしたい dbt モデルの yaml ファイルの編集
  2. dbt モデルの新バージョンの SQL ファイルの新規作成
  3. バージョン管理する dbt モデルを参照するモデルの SQL の編集

下記のようなモデルで考えてみると、

このように整理できます。

番号ファイル
1dim_clients_v1 の schema yaml ファイル
2dim_clients_v2 の SQL ファイル
3orders の SQL ファイル

yaml ファイルの編集

例えば、dim_clientsのカラム名を変更するというシナリオを考えてみましょう。

dbt モデルのスキーマを記した yaml ファイルを下記のように編集します。

models:
  - name: dim_clients
    latest_version: 1
    columns:
      - name: name
        description: client name
        data_type: string
      - name: client_address
        description: client address
        data_type: string

      - v: 1
        config:
            alias: dim_clients

      - v: 2
        columns:
          - include: all
            exclude: [client_address]
          - name: address

latest_version

latest_version によって、最新のバージョンを宣言します。

今回は 1 としているため、最新バージョンはバージョン 1 となり、バージョン 2 はプレリリース版となります。

v: 1

バージョン 1 のモデル定義を記述します。

v: 1 よりも上部に記述されているモデルの定義が継承されるため、重複して定義を書く必要はありません。

config として alias: dim_clients とすることで、変更を加える前の v1 のモデルを dim_client の名称で作成することができます。

デフォルトでは dim_clients_v1 モデルが作成されますが、モデル名は dim_clients のままのほうが都合がいいケースも多いと思いますので、その点を制御できるのはありがたいです。

v: 2

バージョン 2 のモデル定義を記述します。バージョン 1 との差分に注目して記述していきます。

今回のシナリオでは v: 2 でカラム名を変更する対応を行いたいため、include: all として前述のカラムをすべて継承しつつ、exclude: [client_address] によって変更対象のカラムを除きます。そのうえで、name: address として変更後のカラム名を追加します。

以上で yaml ファイルの編集は完了です!

dim_clients モデルを dbt run すると、バージョン 1 と 2 のモデルがそれぞれ作成されます。

$ dbt run --select "dim_clients"

SQL ファイルの新規作成 (新バージョンのモデル)

では、dbt モデルの新バージョンを追加するにあたり、新バージョン用の SQL ファイルの新規作成を行いましょう。

現在、下記のような SQL であったとします。

with

source_cte as (
...
),
...
select
    name,
    client_address -- 変更前のカラム名
from any_cte

今回のシナリオはカラム名の変更を想定しているため、下記のような SQL ファイルを用意します。ファイル名は dim_clients_v2.sql とします。

with

source_cte as (
...
),
...
select
    name,
    address -- 変更後のカラム名
from any_cte

dbt Model Versions では、バージョンごとに SQL を作成することで、モデルのバージョン管理をすることができます。

- dim_clients.sql
  - バージョン 1 用の SQL (元々の SQL- dim_clients_v2.sql
  - バージョン 2 用の SQL

SQL ファイルの編集 (バージョン管理したモデルを参照するモデル)

次に、バージョン管理したモデルを参照するモデルの SQL ファイルの編集を行います。

再掲となりますが、dim_client を参照する orders というモデルがあるとします。

orders において dim_client を参照する SQL が下記のようであったとすると、

src_dim_client as (
    select
        name,
        client_address -- 変更前のカラム名
    from {{ ref('dim_client') }}
),
...

バージョン 2 を参照したいときには下記のように編集します。

src_dim_client as (
    select
        name,
        address -- 変更後のカラム名
    from {{ ref('dim_client', v=2) }}
),
...

また、今回の場合、バージョン 1 を引き続き参照したい場合は、下記のような表記が可能です。

src_dim_client as (
    select
        name,
        client_address
    from {{ ref('dim_client', v=1) }}
),
...
src_dim_client as (
    select
        name,
        client_address
    from {{ ref('dim_client') }}
),
...

バージョン間での参照の切り替えがとても容易にできます!

はまったエラー

最後に、つまづいたポイントを 1 点ご紹介します。

dbt Model Versions を試している中で、ephemeral なモデルに対してバージョニングしようとしたところ、エラーとなってしまいました。

Database Error in model [ephemeral model name] ([ephemeral model path]/[ephemeral model]_v2.sql)
Table "__dbt__cte__[ephemeral model name]_v2" must be qualified with a dataset (e.g. dataset.table).

原因のクエリをコンパイルして見てみると、

...
 __dbt__cte__[ephemeral model name] as (
...
   select * from [ephemeral model name]
),

src_XXX as (
    select
        AAA,
        BBB,
        ...
    from __dbt__cte__[ephemeral model name]_v2
),
...

CTEs は __dbt__cte__ ... という命名で作成されている一方、後続処理の from 句では __dbt__cte__ ... v2 で参照されていました。

このように ephemetal モデルの CTEs の命名および参照がうまくいっていないことがわかります。

私が試行してみた限りだと、dbt Model Versions による ephemeral モデルのバージョニングはできませんでした...😓

たしかに、ephemeral モデルはデータウェアハウス上に現れない層であるため、少なくともデータ利用者からの参照はないことを踏まえると、バージョニング管理対象外なのもなんとなく腑に落ちるような...?

もしかしたら、今後のアップデートで変わるかもしれないので、その点はチェックしてみたいです。

まとめ

以上、dbt Model Versions を使って、dbt のバージョン管理をできるようにしてみました。

バージョンごとにモデル定義を用意する必要がなく、どのバージョンが存在し、どのバージョンが最新なのかがコードベースで残るのは便利ですね。

また、deprecation_date と組み合わせて使用することで、古くなったモデルの整理・削除もしやすくなりそうです。

dbt のモデルをコピペでバージョン 1,バージョン 2 と作りたくなったら、dbt Model Versions を検討してみるとよいかもしれません。

Belong ではこのように dbt を用いた DWH の構築を積極的に実施しています!dbt がお好きな方、少しでも気になるよというははぜひ Belong Engineering Careers をご覧ください!