Open3

【dbt】dbt snapshot

YuichiYuichi

https://docs.getdbt.com/docs/build/snapshots

公式

https://tech.timee.co.jp/entry/2024/06/11/151948#insert処理宛先テーブルに無いレコードがソーステーブル側に新規で作成されていた場合

delete処理:宛先テーブルに存在するレコードがソーステーブルでdeleteされていた場合
update処理:宛先テーブルと比較してソーステーブルのレコードがupdateされていた場合
insert処理:宛先テーブルに無いレコードがソーステーブル側に新規で作成されていた場合
細かく挙動が説明されていた

https://data.gunosy.io/entry/dbt_snapshot_and_scd

Slowly Changing Dimension の Type 0~7 が何を意味しているのかわかる

https://qiita.com/Ayumu-y/items/af48189c8168c7030707

わかりやすい

{% snapshot daily_data_snapshot %}

{{
  config(
    target_database=[BigQueryで言うところのプロジェクト名]
    target_schema=[データセット],
    unique_key=[主キー],
    strategy='timestamp',
    updated_at=[date型のカラム。ここに指定した列を最終更新日時として、既存テーブルと比較して更新された行をINSERTする],
  )
}}

select
    *
from
    {{ source([データセット名], [テーブル名]) }}

{% endsnapshot %}
YuichiYuichi

https://dev.classmethod.jp/articles/dbt-try-snapshot/

snapshotに関するベストプラクティス

snapshotはとても便利な機能なのですが、使い方を誤ると、全く活用されない大量のデータを保持してしまうなど、リスクに繋がる可能性があります。

以下は公式Docからの引用ですが、snapshotに関するベストプラクティスを、私なりに解釈してまとめておきます。

  1. Strategyはできる限り「timestamp」を使用する
    • 差分を効率的に検知し、最適なデータ更新を行うためです。
  2. unique_keyが本当にユニークであることを確認する
    • unique_keyはスナップショットを正確に機能させるために重要です。unique_keyの一意性を保証するためにschema testを設定することも推奨されます。
  3. Snapshot用に別のスキーマを定義する
    • 分析用データとスナップショットを別スキーマにすることで、意図しない削除からデータを保護できます。Snowflakeなどでは、スナップショット生成時に別のロールを使用して削除を防ぐといった運用も可能です。
  4. Sourceに対してSnapshotを行う
    • クレンジング処理を行う前の生データをスナップショットすることが理想です。元データをそのまま保存することで、将来のデータ追跡に役立ちます。
  5. Sourceを参照する際はsource関数を使う
    • source関数を使うことで、データリネージが追跡可能になり、データの出所を明確にすることができます。
  6. Snapshotには、できるだけ多くのカラムを選択する
    • 可能であればselect *を使用し、将来的に利用する可能性があるカラムをすべてスナップショットするのが理想です。
  7. SnapshotのSELECT文でJOINを避ける
    • JOINを含むクエリは、timestampの信頼性を損なう可能性があります。JOINが必要な場合は、各元テーブルごとにスナップショットを取ることを検討してください。
  8. SnapshotのSELECT文でデータのクレンジングやロジックの実装を避ける
    • クレンジング処理やロジックは将来的に変更が必要になる可能性があるため、シンプルなクエリでスナップショットを取ることが推奨されます。ただし、JSONのカラムを展開する場合などは例外です。

これらのポイントを守ることで、スナップショットの効果的な活用とデータの管理がスムーズになります。