🛵

ベストプラクティスから読んで始めるdbt

2022/02/21に公開

概要

  • dbtと仲良くなりたい私
  • dbtを社内でも広めたい私
  • ディレクトリ構成とかどうしていけばいいか分からない私
  • よし、まずはdocsのbest practiceを読んでみよう
  • 後に同僚にも読んでもらいやすようにまとめておこう

ということでこれを読んでいきます
しっかり公式のdocs読むこと大切よね

https://docs.getdbt.com/docs/guides/best-practices

余計なお世話かもしれませんが、途中私が気になったことに対しては以下のようにコメント残していきます

Best practice workflows

Version control your dbt project

  • 全てのdbtプロジェクトはバージョン管理しようね
  • 新しい機能やバグの修正のためにはブランチを生やして作業しようね
  • 全てのコードの変更はプルリク出して、同僚に(もしくは自分で)レビューしてもらおうね

Use separate development and production environments

  • dbtでは、プロファイル内のtargetを使用することで、本番環境と開発環境を別々に維持することが容易だよ
  • コマンドラインからdbtを実行する場合はdevターゲットを使用し、本番環境から実行する場合はprodターゲットに対してのみ実行することをお勧めするよ
  • 環境の管理の詳細はこちら

Use style guide and for your project

  • SQLスタイル、フィールドの命名規則など、dbtプロジェクトのルールは体系化する必要があるよ
  • まずはdbtお勧めのスタイルガイドから始めるといいよ

Best practices in dbt projects

Use the ref function

  • dbtを最強たらしめるのはref関数だ!
  • dbtは依存関係を推論し、モデルが正しい順序でビルドされることを保証するよ
  • 現在のモデルが作業しているのと同じ環境の上流のテーブルやビューから選択されるようにするよ
  • 他のモデルから選択するときは直接の参照を使うのではなく、常にref関数を使うようにしなさい

Limit references to raw data

  • dbtプロジェクトはデータベースに保存されている生データに依存するよ(ソリャソウジャ)
  • こういうデータは変更される可能性があるので、データソースへの参照を最小限にとどめるとモデルの更新が簡単に済むよ
  • v0.13.0では、生データ(データソース)をsourceとして定義し、直接参照を使用するのではなく、ソースから選択することを推奨してるよ、もはやdbtプロジェクトではどのモデルにも直接参照をしなくても済むよ(詳細はこちら)

Rename and recast fields once

  • 生データは一般にソースに準拠した構造、つまりソースが定義するスキーマや命名規則に従って保存されるよ
  • この構造はソースごとに異なるだけでなく、分析に使用したい命名規則とも異なることがあるよ
  • dbtプロジェクトの最初のレイヤーは次のような振る舞いをするべき
    • 1つのソースのみから選択する
    • 例えば全てのタイムスタンプの名前を<event>_atにするなど、プロジェクト内で使用したい規則に合わせてフィールドやテーブルの名前を変更する、これらの規約はプロジェクトのコーディング規約で宣言すること
    • フィールドを正しいデータ型にキャストし直す、例えば日付をUTCに、価格を円に変更する
  • これを最初にやっちゃえば、この後のモデルで重複するコードの量を減らせるよ

Break complex models up into smaller pieces

  • 複雑なモデルでは複数のCTE(Common Table Expressions)を含むことがあるよ
  • dbtでは代わりにこれらのCTEを別々のモデルに分割して、その上に構築することができるよ
  • 複雑なモデルを分割するのは、次のような場合によく行われるよ
    • CTEが2つのモデルで重複している場合、CTEを別のモデルに分割することで下流のモデルでそのモデルを参照できるようになり、コードの重複を減らせるよ
    • CTEは選択するデータの粒度を変更するよ、データの粒度を変更するようなテストをすることは有用だよ、CTEを別のモデルに分割することで、この変換をより大きなモデルから独立してテストすることができるよ
    • クエリのSQLには多くの行が含まれているよ、CTEを別のモデルに分割することで、他のdbtユーザー(もしくは未来の自分)がコードを見るときの認知負荷を軽減することができるよ

Group your models in directories

  • models/ディレクトリの中に任意の数のネストしたサブディレクトリを持つことができるよ
  • サブディレクトリを使って構造を整理していこう
    • dbt_projct.ymlファイルで設定を指定し、モデルグループを構成する
    • モデル選択構文を使用して、DAGのサブセクションを実行しよう(?)
    • 共同編集者とモデリングの手順を合意しよう
    • 例えば、「martsディレクトリのモデルは、martsディレクトリの他のモデル、またはstagingディレクトリのモデルからしか選択できない」というように、モデルの上流依存関係を許容する規約を作成しよう

Add tests to your models

  • dbtはモデルによって生成された結果に関するテストができるようになっているよ
  • プロジェクトにテストを追加することで次の2点を保証できるよ
    • 自分が書いたSQLが期待通りの方法でデータを変換していること
    • ソースデータに期待する値が含まれていること
  • スタイルガイドでは、全てのモデルが最低限primary keyがユニークであり、nullでないことを確認するためのテストを行うことを推奨しているよ

Consider the information architecture of your data warehouse

  • SQLクライアントでデータウェアハウスに接続した場合、ユーザーはスキーマ、リレーション、カラムの名前を頼りに表示されるデータを理解することがよくあるよ
  • データウェアハウスが持つこれらのメタデータを改善するために次のようなことを行っているよ
    • カスタムスキーマを使用して、リレーションを論理的なグループに分離したり、中間モデルを別のスキーマに隠したりするよ、一般的に、これらのカスタムスキーマは、モデルのグループ化に使用するディレクトリと一致し、dbt_project.ymlファイルから設定されるよ
    • テーブル名の接頭辞(例えば、stg_fct_dim_)を使用して、エンドユーザーが照会すべきリレーションシップを明示するよ

Choose your materializations wisely

  • マテリアライゼーションは設定によってモデルを構築する方法を決定するよ、一般的なルールとして、
    • ビューはテーブルと比較して、構築は高速ですが、クエリーは遅くなるよ
    • インクリメンタルモデルは、テーブルと同じクエリーパフォーマンスを提供し、テーブルのマテリアライゼーションと比較して構築は高速だけど、プロジェクトに複雑さをもたらすよ
  • 下記パターンを推奨しているよ
    • デフォルトでビューを使用する
    • エンドユーザーに公開されるべきでない軽量の変換には、エフェメラルモデルを使用する
    • BIツールで照会されるモデルにはテーブルを使用する
    • 複数の子孫を持つモデルにはテーブルを使用する
    • テーブルモデルの構築時間が許容範囲を超えた場合、インクリメンタルモデルを使用する

Pro-tips xxx

pro tipsは現在の私の知りたいスコープとは外れるかなと思うので、強くなったらまた帰ってきます


最後に未来の私へのメモ

Discussion