dbtにおけるモデル(models)の記法に関するベストプラクティス #dbt

2024.03.31

アライアンス事業部 エンジニアグループ モダンデータスタック(MDS)チームのしんやです。

dbtはクラウド型データウェアハウス(DWH)におけるデータ変換に特化したツールです。非常に使い勝手が良く便利なツールである一方、様々な機能が提供されているのでいざ使ってみよう!となると『何をどうやって作り上げていけば良いんだろう?』『この場合のルールや制限はどういうものがあるの?どういう取り決めをもって扱えば良いんだろう?』という風に思うこともあるかと思います。(実際私自身そう感じました)

そんなユーザーの疑問や悩みを解決する、いわゆるdbtユーザー向けのガードレール的な存在となりうるコンテンツがdbt社から展開されています。それが『dbtベストプラクティスガイド(Best practice guides)』です。構造、スタイル、セットアップなど、dbt Labsの現在の視点を通した「ベストプラクティス」がまとめられています。

そこで当エントリでは、幾つか展開されている「dbtベストプラクティスガイド」で紹介されているコンテンツの中から『dbtにおけるモデル(models)の書き方』に関するものを紹介し、読み解いていきたいと思います。

目次

 

dbtモデル(dbt models)の記法に関するベストプラクティス

 

モデルの名称

  • ✅ モデルの名前は複数名とすべきです。
    • 例) customers, orders, products
  • dbtモデルの名称にはアンダースコアを使用し、ドットは避けましょう。

 

モデル内の各種要素・項目の書き方

  • ✅ 各モデルは主キー(Primary Key)を持つべきです。
  • ✅ モデルにおける主キーの名称は account_id のように、<object>_id という名前にしましょう。これにより、下流の結合されたモデルでどのidが参照されているのかを簡単に知ることができます。
  • ✅ キーは文字列データ型でなければなりません。
  • ✅ スタイルガイドを定める上では「一貫性」が何より重要です。可能であれば、モデル間で同じフィールド名を使いましょう。たとえば、customersテーブルのキーはuser_id'id'ではなく、customer_idという名前にすべきです。
  • ❌ 略語や別名は使用せず、簡潔さよりも読みやすさを重視してください。customercustordersoというような略称を使ってしまうと混乱を招きかねません。
  • ❌ dbtで対応しているデータウェアハウスで使われている予約語をカラム名として使用しないようにしてください。
  • ✅ ブール値(boolean)にはis_またはhas_を先頭に付けてください。
  • ✅ タイムスタンプに関する列名は<event>_at(例えばcreated_at)と命名すべき、且つUTCであるべきです。
  • ✅ 日付に関する列名は<event>_dateとすべきです。
    • 例) created_date
  • イベントに関する列名は「過去形」表記にすべきです。
    • 例)
      • created(作成された)
      • updated(更新された)
      • deleted(削除された)
  • ✅ 価格/売上に関する列名は10進数で指定すべきです。
    • 19.99ドルの場合は19.99:多くのアプリデータベースは価格をセント単位の整数として保存します。
    • 10進数以外の通貨を使用する場合は、接尾辞を付けましょう。 例) price_in_cents
  • ✅ スキーマ名、テーブル名、カラム名はsnake_caseでなければなりません。
    • スネークケース(snake_case)とは、単語のつなぎ目を「_(アンダースコア)」で接続し、各単語の最初の文字を小文字で書く書式。
    • スネークケース - Wikipedia
  • ✅ データソースに関する用語ではなく、ビジネス用語に基づいた名前を使用するようにしてください。
    • 例) ソース・データベースがuser_idを使用しているが、ビジネスではcustomer_idと呼んでいる場合、モデルではcustomer_idを使用します。
  • ✅ モデルのバージョンは、一貫性を保つために接尾辞_v1_v2などを使用しましょう。
    • 例) customers_v1customers_v2
  • ✅ データ型の順序を統一し、下の例のように、型ごとに列をグループ化し、ラベルを付けることを検討してください。このような形にすることで、結合エラーを最小化し、モデルを読みやすくします。
    • また、データの下流の消費者がデータ型を理解し、必要な列のためにモデルをスキャンするのを助けます。idstringnumericsbooleandatestimestampsの順で使用するのが望ましいです。

 

共通テーブル式(CTE/Common Table Expression)を使用

dbtにおけるSQLモデルの記述は、共通テーブル式(CTE/Common Table Expression)で書くことを推奨しています。この書き方を踏襲することで複雑な処理が(他者にとっても)読みやすくなる、処理のボトルネックやエラー等発生した際の特定もしやすくなる、といったポイントがその理由となっています。この辺りは普段からCTEを使っていないと慣れない部分かなと思いますが、言われてみれば確かに!という感じでもありますので、ここはこのルールに従い、いい感じでCTEを活用していくようにしていきたいですね。

「なぜdbt SQL modelsでCTEを使うのか」については 『イチから始めるデータ活用!dbt編』で発表したスライド資料でも言及しています。

 

SQLモデルではSELECT文で処理を記述

前述『共通テーブル式(CTE)』を使うということは、必然的に(SQL)モデル内ではSELECT文(Select statetment)を使う形となります。これについてもdbt社ではその理由・ポイントを幾つか紹介しています。

「なぜdbt SQL modelsでSELECT文を使うのか」については 『イチから始めるデータ活用!dbt編』で発表したスライド資料でも言及しています。

 

(SQL)モデルの記法サンプル

上記のルールを踏まえた形での「記法サンプル」は以下のようなものになります。

with

source as (

    select * from {{ source('ecom', 'raw_orders') }}

),

renamed as (

    select

        ----------  ids
        id as order_id,
        store_id as location_id,
        customer as customer_id,

        ---------- strings
        status as order_status,

        ---------- numerics
        (order_total / 100.0)::float as order_total,
        (tax_paid / 100.0)::float as tax_paid,

        ---------- booleans
        is_fulfilled,

        ---------- dates
        date(order_date) as ordered_date,

        ---------- timestamps
        ordered_at

    from source

)

select * from renamed

 

まとめ

という訳で、dbtにおけるベストプラクティスの1つ『dbtモデルの記法に関するベストプラクティス』の紹介でした。

dbtにおける中核処理である『モデル』については一番触れる機会が多い、記述量が多くなる要素となります。dbtならではの癖のようなもの(例えばCTEとか)もについては慣れが必要ではありますが、理由を紐解いてみると納得出来る部分もありますのでこれはこれで『ルールに従う事の効果』を期待しつつ身に付けて行きたいところではありますね。