7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

dbtでRecceを使うといい感じに修正の検証ができて良い

Last updated at Posted at 2024-05-31

dbtでのデプロイの検証について

dbtに限らずETLプロセスの修正をデプロイする際には、修正の影響がある指標・属性について以下のような検証を行う必要がある (と思っている)

  • 修正前後で集計結果に差異がないか
  • 修正前後で集計結果に差異は発生しているが、発生原因は説明がつくものか 1

dbt(v1.8~)で用意されているテストとして以下の2つがあるが、これらのテストだけでは、上記が問題ないことを保証しきることは難しいと思っている

  • Data tests : 主にデータの品質確認のために実施する
  • Unit tests : 主にモデルのロジックが正しいかを実施する

Recceを使えば、dbtの修正の検証が容易にでき、かつ検証の自動化まで行えそうなことが分かったため、使用方法やどんな感じのことができるかをまとめたいと思う

Recceについて

以下は公式サイトからの引用

Recce is a data-change validation tool for dbt projects. Recce provides a convenient platform to perform cross-environment diffs as data modeling validations. Use these validations in your pull request (PR) comment to demonstrate proof-of-correctness of your modeling changes and speed up thew QA process of PR review.

Recceはdbtの異なる環境間を比較検証するためのプラットフォームで、プルリクでRecceを使うことで、検証のプロセスを加速させることができるよ、というようなことを書いていると思う

使い方

説明の都合上、どのようにすれば使えるかを先に説明する

デモ用のリポジトリを用意しているので、こちらを使えばRecceを手元で確認できると思う

手順

前提として、環境が2つ以上必要となる。以下はDuckDBにつなぐ際のprofiles.ymlの例である 2

jaffle_shop:
  target: dev
  outputs:
    dev:
      type: duckdb
      path: 'jaffle_shop.duckdb'
      schema: main
    prod:
      type: duckdb
      path: 'jaffle_shop.duckdb'
      schema: prod

Recceをインストールする

pip install -U recce

Recceの機能をフルに使うために、package.ymlに以下の2つのパッケージを追加したうえで、dbt depsを実行する

packages:
  - package: dbt-labs/audit_helper
    version: 0.11.0
  - package: data-mie/dbt_profiler
    version: 0.8.1

Recceはdbt docsと同様にRecceサーバーをlocalにホストして、Webブラウザ上で使うことになるが、Recceサーバーをホストするために以下の2つのアーティファクトが必要となる

  • manifest.json
  • catalog.json

そのため、これらのアーティファクトを比較元(prod環境)と比較先(dev環境)で用意する必要がある。さらに、アーティファクトの保存先を以下のように環境ごとに分ける必要がある

環境 アーティファクトの保存ディレクトリ
prod環境 target-base/
dev環境 target/ (デフォルトの保存先)

比較元(prod環境)でのアーティファクト作成は以下のように行う

git switch main # mainブランチがprod環境と同期していると仮定

dbt build -t prod
dbt docs generate -t prod --target-path target-base/

比較先(dev環境)でのアーティファクトの作成は以下のように行う

git switch feature/my-awesome-feature # 修正を行っているブランチに移動する

dbt build
dbt docs generate

最後に、Recceサーバーを起動する。サーバーへはブラウザからアクセスできる

recce server

Recceの特徴

Recceは以下のような機能を含んでいる

  • WebUIによる修正の検証
  • CLIによる修正の検証・検証の自動化
  • 検証結果をstateファイルとして保存・共有する
  • 定常的に行う比較をpresetとして登録・コード管理し、自動的に検証できるようにする

WebUIによる修正の検証

Webブラウザからは以下の3つのページが確認できる

  • Lineage
  • Query
  • Checks

Lineageページ

Recceで基本となるところ(だと思っている)で、リネージグラフ上で修正があったモデルのみが確認できる。非常に見やすい (修正があったモデル以外も含めて表示することも可能)

lineage.png

リネージグラフ上の各モデルをクリックすると、モデルごとの比較結果が確認できる(画像では、ordersをクリックしている)

orders.png

デフォルトでは、スキーマの比較画面とカラム数の比較(99 rowsのところ)が見られる。上の</> Diff、下のAdvanced Diffsをクリックすることで、そのほかの比較が確認できる

</> DiffをクリックするとモデルごとのコードのDiffが確認できる。リネージグラフからたどり着いているので、GitHub上で確認するよりもコードの理解度が高くなると思う

codediff.png

Advanced Diffsからは現状4種類の比較ができる

項目 比較内容 特に有用なカラム
Profile Diff カラムごとに基礎統計量を比較する any
Value Diff カラムごとにどのくらい値が一致しているかを比較する any
Top-K Diff 選択したカラムについて、取りうる値ごとに値の件数を比較する。占有割合が大きい順にソートされて表示される カテゴリカラム
Histogram Diff 選択したカラムを基にヒストグラムを作成し、比較する 数値カラム

実際の画面は以下のようになる

  • Profile Diff

profile.png

  • Value Diff

value_diff.png

  • Top-K Diff

top_k.png

  • Histogram Diff

histogram.png

Add checkAdd to checklistをクリックすると後述するChecksページに比較結果を追加できる

Queryページ

クエリを修正前後のモデルに対して発行して、クエリ結果を簡単に比較できる。クエリにはJinjaテンプレートを使用できる(ref以外のマクロも使えると思う)

query.png

UIは以下のようになっている

  • Runボタンもしくはcommand(ctrl)+Enterでクエリを実行可能。Run diffで修正前後の両方のモデルに対してクエリを実行し比較できる
  • 画面右のPrimary keyが修正前後を比較する際のキーになる(なくても比較はできる)
  • 画面右下のChanged onlyをオンにすれば、差異があったレコードだけに絞れる
  • クエリ結果右上の+から、Checksページに比較結果を追加できる

Checksページ

今までで追加した比較結果ともともとpresetとして設定されていた比較結果を確認できる。
各比較結果にはチェックをつけることが可能

preset.png

比較結果のコピー・保存

比較結果のコピーと保存は以下のように簡単にできる

  • 比較結果を画像としてコピー
    • Lineageページでいうと、下画像右端の赤枠で囲ったコピーマークをクリックすると、リネージグラフのコピーができ、プルリクのコメント等にそのまま貼り付けることができる(貼り付けた結果)。ほかの画面でもワンクリックでコピーができる
  • 比較結果をstateファイルとして保存
    • 画面右上のエクスポートボタンを押すと、Checksで新たに追加した比較結果を含めてstateファイルとして保存ができる。stateファイルについては後述する

save.png

CLIによる修正の検証・検証の自動化

CLIコマンドとしては以下の2つが用意されている

コマンド 処理内容
recce run 比較結果をstateファイル(recce-state.json)に出力
recce summary stateファイルのサマリをmd形式で表示

recce summaryコマンドによって生成される結果は、githubのコメント用に最適化されている(表示例)ので、例えば、Github Actions内で、

  1. recce runでステートファイル作成
  2. recce summaryでサマリのテキスト作成
  3. ghコマンド等でサマリのテキストをプルリクのコメントとして追加

とすることで、CI/CDに組み込むことができる

上記を含む内容をすでに公式は用意しているので、詳しい実装に興味がある人は以下リンクを確認してほしい

検証結果をstateファイルとして保存・共有する

WebUIやCLIの説明ですでに登場しているが、比較・検証結果をstateファイルというjsonファイルに保存できる

作成したstateファイル(=recce-state.json)を元に以下コマンドを使うと、レビューモードでRecceサーバーを起動できる

recce server --review recce-state.json

stateファイルは以下の情報から構成される

項目 JSONキー 内容
Checks "checks" Checksページに表示されている比較の設定
Runs "runs" Checksページに表示されている比較の実行結果
Environments' Artifacts "artifacts" 比較元と比較先のアーティファクト(=manifest.json, catalog.json)
Runtime Information "git" gitのブランチの情報など

例えば、プルリクのレビュープロセスにおいて、プルリク作成者がstateファイルを保存し、レビュアーに共有することができる。レビュアーは、レビューモードでReccaサーバーを起動することで、

  • 比較の実行結果(=Runs)が保持されているので、レビュアーはクエリを実行することなく比較・検証結果を確認できる
  • アーティファクト情報が保持されているので、レビュアーはdbt docs generateなどの追加のコマンドなしに、Recceサーバー上で比較クエリを発行することができる

定常的に行う比較をpresetとして登録・コード管理する

dbtプロジェクトのルートディレクトリに以下のような内容を、recce.ymlとして保存することで、RecceサーバーのChecksページ上にpresetとして登録することができる
また、recce runコマンドでも、presetとして登録された比較が実行されるので、比較を自動化する際には必須の設定となる

checks:
  - name: Query diff of customers
    description: |
        This is the demo preset check.

        Please run the query and paste the screenshot to the PR comment.
    type: query_diff
    params:
        sql_template: select * from {{ ref("customers") }}
    view_options:
        primary_keys:
          - customer_id
        changed_only: true

現在は設定項目に関するドキュメントはないので、WebUIからコードを取得するしかない(下画像参照)が、検証の自動化のためには強力なツールとなる

preset_code.png

読み方

Recceは「レーキー」と読むらしい(/ˈrɛki/: 'reconnaissance'の略)

注意事項

stateファイルについて

前述したように、stateファイルはクエリの実行結果を含むので、クエリ結果に個人情報が含まれないように気を付ける必要がある。そのため、例えば以下のような対策が必要になってくると思われる

  • カラムレベルマスキング等でクエリを行っても個人情報が表示されないようにする
  • CI/CDで自動化する際に生成されるstateファイルを定期的に削除する

Snowflakeでの使用について

Snowflakeをよく使うので、Snowflakeで使用するうえでの注意点をまとめておく

Snowflake上で実行する場合のprofiles.ymlは以下のようになると思われる

jaffle_shop:
  target: dev
  outputs:
    dev:
      type: snowflake
      account: <orgname>-<account_name>
      role: dev_role
      database: dev_db
      schema: public
      warehouse: dev_wh
      user: "{{ env_var('DBT_USER') }}"
      password: "{{ env_var('DBT_PASSWORD') }}"
    prod:
      type: snowflake
      account: <orgname>-<account_name>
      role: prod_role
      database: prod_db
      schema: public
      warehouse: prod_wh
      user: "{{ env_var('DBT_USER') }}"
      password: "{{ env_var('DBT_PASSWORD') }}"

Recceの挙動

recce serverを実行する際の挙動は以下のようになっている

参照 profiles.ymlの設定項目
常に環境ごとの設定値が参照されるもの database
コマンド実行時に指定した環境の設定値が参照されるもの warehouse, role

profiles.ymlに記載した通り、databaseは比較元と比較先で異なるものを設定していても大丈夫だが、ウェアハウスとロールはコマンド実行のものとなる (おそらくユーザーも)
つまり、上記のprofiles.ymlに記載した通りの設定を行った場合、下表のようになる

実行コマンド 実際に使用されるロール 実際に使用されるウェアハウス
recce server dev_role dev_wh
recce server -t prod 3 prod_role prod_wh

例えば、dev_roleprod_dbへのアクセス制限がない状態でrecce serverを実行すると、比較を行うクエリが権限不足で失敗してしまうので、例えば以下のいずれかで対応する必要がある

  • prod_roledev_dbへの読み取り権限を与え、recce server -t prodと実行するようにする
  • prod_dbdev_dbの両方に読み取り権限を持つロールrecce_roleを追加して、recce用のprofileを作る。実行はrecce server -t recceとする
        recce:
          type: snowflake
          account: <orgname>-<account_name>
          role: recce_role
          database: dev_db
          schema: public
          warehouse: recce_wh # recce用のウェアハウス
          user: "{{ env_var('DBT_USER') }}"
          password: "{{ env_var('DBT_PASSWORD') }}"
    

いずれも方法においても、レビューモードでは注意が必要
レビューモードでも同様にターゲットを指定して実行することが可能になっている 4

その他細かい注意点

  • プリセットで説明したrecce.ymlのprimary_keysだが、Snowflakeの場合は通常大文字で指定してやる必要がある

    • Recce内部では、primary_keyで指定したものが、データベース上に存在するか確認しているっぽい
    • 現状その照合で大文字と小文字を区別しているので、小文字にすると、primary_keyがないとエラーになる
            primary_keys:
              - CUSTOMER_ID
    

できないこと

  • 参照先のDBが異なる場合は利用できない(devをDuckDB、prodをSnowflakeにする等)
    • そのため、dbtの基盤を別DBに移行するというシナリオでは使用できないと思われる
  • dbtでの検証を対象にしているため、DWHの移行で既存のETLをdbtにリプレイスする際の検証にも使用できない

最後に

見つけた勢いのまま書いてしまったが、いい感じのパッケージなので、今後積極的に使っていきたいと思った(いい感じを多用している)

参考

  • 公式ドキュメント

  • ここで、Recceの紹介がされていた

  • ベストプラクティス

  • 公式のプルリクのデモ(いい感じ)

  1. 返品した商品を売上から除外するように修正したため、売上は修正前に比べて小さくなったとか

  2. pathについて、環境ごとに違うファイルを指定することは可能だが、この場合は、Recceはエラーとなってしまう

  3. recce server時に、--targetもしくは-tを指定することで、実行時の環境が選べるようになっている

  4. レビューモードの場合は、targetオプションが効かず、デフォルトの環境を参照するようになっていると思われる。バグっぽいので、Issueで問い合わせ中 → 問い合わせた結果、すぐに修正してもらうことができた (v0.20.1) :relaxed:
    ただ期待されていた挙動としては、stateファイル作成時の環境で実行されることっぽいので、将来的には、stateファイルにtargetの情報が含まれる + レビューモードではtargetの指定が不要( → stateファイルのtargetの情報が使用される)みたいになるかもしれない

7
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?