なむなむ

@namb_nam による恥晒し

dbtのベストプラクティスを知る①

ベストプラクティスから読んで始めるdbt という記事が、とても素晴らしいなと。

  • しっかり公式のdocsを読む
  • 自分なりの感想(得られた事項)を持つ
  • わからないこともメモしておく

同じようにやってみよう。
馬鹿みたいだけど、同じ記事で。
(ついでに英語のリーディングも頑張ろう)

docs.getdbt.com

Best practices

  • ベストプラクティスを見ておくことで、可能な限り効率的になる
  • プロのTipsを実装すればdbtプロジェクトが洗練される

Best practice workflows

Version control your dbt project

  • dbtプロジェクトはヴァージョン管理せよ
    • 新機能・バグ修正のためにGitブランチを切れ
    • マスターブランチにマージする前にコード変更はプルリクでレビューせよ
    • Gitガイド
Gitの説明が丁寧だな... 
過去の状態がわかっていると、何か起きた時にバックアップしやすいか

Use separate development and production environments

  • profileのtargetを使うことで、prod環境とdev環境を分けて管理できる
  • 自分のローカル環境で動かす際はdevに対して、本番環境で動かすときはprodに対してのみ実行すべし
  • about managing environments
自分の作業が本番に影響しないのはいいな
ところでこのdev環境はどこに作られるのかしら

Use a style guide and for your project

ルールの徹底は難しい。揃っていたほうがいいに決まっているが...

Best practices in dbt projects

Use the ref function

  • ref関数はdbtを強力にしているもの
  • ref関数を使えば、
    • dbtは依存関係を推測できる
    • モデルを正しい順序で構築できる
    • 作業している環境の上流のテーブル/ビューから選択することを保証する
  • 他のモデルから選択するときは、直接参照(例:my_schema.my_table)ではなく、ref関数を使え
依存関係が決まっているだけで、更新順序を指定する必要がなくなるのだからすごい

Limit references to raw data

  • dbtプロジェクトはデータベースのローデータに依存する
  • ローデータは通常サードパーティーによってLoad(読み込み)されるので、その構造が時間と共に変化する恐れがある(テーブルやカラムが追加されたり、削除されたり、リネームされたり)
  • これらが起きたとき、ローデータを1箇所でだけ参照していれば、モデルのアップデートは容易
  • ローデータはsourceとして定義するのが推奨される(直接参照するのではなく)
    • そうすればどのモデルにも直接参照がなくなる
つまりローデータを参照するモデル数を減らせ、という意味だな
直接参照を忌避している理由は、依存関係を明らかにしたいからだけ?

Rename and recast fields once

  • ローデータは一般にソースが定義するスキーマ命名規則に従って保存される
    • この構造は、ソースによって異なるし、分析に使いたい命名規則とも異なる場合がある
  • dbtプロジェクトの最初の変換は、以下のルールですべき
    • 1つだけのソースから作る
    • テーブルやカラムは、プロジェクトで使いたいように(ルールに従って)リネームする
    • 正しいデータタイプ(タイムゾーンや通貨)に変換する
  • このモデルを頂点としてすべての後続モデルを作ると、重複するコードを減らすことができる
  • 参考:どのようにdbtプロジェクトを構成するかの意見が書かれた記事
プロジェクトの構成をシンプルにすることが命題なのだな?

Break complex models up into smaller pieces

  • 複数の共通テーブル式(CTE、WITH 句で定義された名前付きサブクエリ)を含むと複雑なモデルになりがち
  • dbtでは別々のモデルに分けることができる
  • 複雑なモデルを分解するのは以下の場合に良い
    • CTEが、2つのモデルで重複している
      • 分割すると下流のモデルがいくつあっても参照できるので、重複コードを減らせる
    • CTEが、選択するデータの粒度を変更する
      • データの粒度(1レコードが表す内容)を変更する変換をテストするのは有用
      • CTEを別のモデルに分割することで、大きなモデルから独立してこの変換をテストできる
    • SQLが多数の行になっている
      • CTEを別のモデルに分割することで、コードを読むときの認知負荷を下げる
とにかく分解せよと。でもモデル数が多すぎると良くないかもな

Group your models in directories

2個目がわからん
ディレクトリには、整理以上の役割があるってことだな?

Add tests to your models

  • dbtには、モデルによって生成された結果についての仮説をテストするためのフレームワークがある
  • プロジェクトにテストを追加することで、以下を保証する
    • SQLが期待通りにデータを変換している
    • ソースデータが期待する値を持っている
  • 最低限、プライマリーキーがユニークかつNULLでないことをテストするのがおすすめ( style guide
複数種類のテスト実装できるの素晴らしい

Consider the information architecture of your data warehouse

  • SQLクライアント経由でデータウェアハウスに接続すると、提示されたデータを理解するためにスキーマ、依存関係、カラムの名前に頼ることがある
  • データウェアハウスの情報アーキテクチャを改善するために、
    • カスタムスキーマを使い、依存関係をロジカルなグルーピングに分解したり、別々のスキーマに中間モデルを隠したりする
      • 一般的に、これらカスタムスキーマはモデルをグルーピングするためのディレクトリと一致し、dbt_project.ymlに記述する
    • stg_などのプレフィックスをつけて、エンドユーザーにクエリ対象を示す
このデータセットに入っているからクエリ対象/非対象、はまだ制御できそうだけど、プレフィックスでできるかな?

Choose your materializations wisely

  • Materialization設定により、モデルの構築方法を決定する
    • Viewは構築が速いが、テーブルに比べるとクエリが遅い
    • インクリメンタルモデルは、テーブルと同等のクエリパフォーマンスで、テーブルより早く構築できるが、プロジェクトが複雑になる
  • 使い分け
    • デフォルトはビュー
    • エンドユーザーに見せなくていい軽い変換はephemeralモデルにする
    • BIツールにクエリされるモデルはテーブルにする
    • 複数モデルに参照されるモデルはテーブルにする
    • テーブルの構築時間が許容範囲を超える場合はインクリメンタルモデルにする
この使い分け、いいな