dbt勉強会 – sourceについて調べてみた

以前に「dbtとBigQueryのクイックスタート」をやりました。
今回はdbtの理解を深めるために、一人でdbt勉強会です!

今回のテーマ

今回のテーマは
「sourceってなーに?」
です!

クイックスタートをやってみたでは、こんなことを書いていました。

ソースをdbtに宣言しておくことで、参照元のテーブルの説明が記載できたり、モデルで行ったテストを実施したりすることができます。

ここで「モデルの方でも同じことできそうだけどなんで分けてるの?」という疑問が浮かんできたので、dbtのsourceを深堀して調べてみます!

結論:なぜソース宣言するのか

dbtは、SQLを読み込んで「どのテーブルを参照しているか」を安全に特定するのが難しいため、refやsource で明示して依存関係を管理する設計 となっています。

依存関係を可視化した時に、末端のデータがどんなデータなのかが管理できるようにsourceを利用しましょう!

ソース宣言でできること

ソースの宣言は、YAMLファイル(.yml)で行います。
dbt_project.yml の model-paths に含まれるディレクトリ配下 に置く必要があり、
model-pathsのデフォルトはmodelsなので、models配下にファイルを設置します。

※ ファイル名は自由なので、models/sources.yml 以外でも問題ありません。

参考:Source properties

ソースの宣言

DWHにある無数のテーブルの中から「dbtの入力として使う元データはこれだよ」と明示することができます。

以下がBigQueryの場合の例になります。

YAML
sources:
  - name: ソース名
    description: 説明
    database: プロジェクトID
    schema: データセット名
    tables:
      - name: テーブル名1
        description: 説明
      - name: テーブル名2
        description: 説明

呼び出し方としては、以下のように記述します。

SQL
SELECT * FROM {{ source('ソース名', 'テーブル名1') }}

おまけ

テーブル名が重複している場合でも、ソース名を重複しないように宣言をしてあげることで、同一のテーブル名を呼び出せます。

YAML
sources:
  - name: source_name1 # ここを重複しないようにする
    description: 説明
    database: project_id
    schema: ec1
    tables:
      - name: user
        description: 説明

  - name: source_name2 # ここを重複しないようにする
    description: 説明
    database: project_id
    schema: ec2
    tables:
      - name: user
        description: 説明
SQL
SELECT * FROM {{ source('source_name1', 'user') }};
SELECT * FROM {{ source('source_name2', 'user') }};

テストの実施(data_tests)

source宣言したテーブルのテストを data_tests を利用することで実施することができます。

userテーブルのuser_idが「ユニークかつnullじゃない」というテストをしたい場合は、以下のように記述します。

YAML
sources:
  - name: source_name1
    database: project_id
    schema: ec1
    tables:
      - name: user
        columns:
          - name: user_id
            data_tests:
              - unique
              - not_null

他にも、ENUM型のチェックや参照先のデータチェックなど様々なテストを実施することができます。詳細については公式のドキュメントをご覧ください。

参考:Add data tests to your DAG

sourceの設定(config)

宣言されたsourceについて、dbt がどう扱うか(実行・管理・表示の挙動)config で制御することができます。

よく使われるケースは、テストの挙動を変える時です。
通常はテストが失敗するとエラーとなりジョブが正常終了しませんが、失敗しても警告が出るだけでジョブ自体は正常終了させることができます。

YAML
sources:
  - name: source_name1
    database: project_id
    schema: ec1
    tables:
      - name: user
        columns:
          - name: user_id
            data_tests:
              - unique
                  config:
                    severity: warn
              - not_null:
                  config:
                    severity: warn
  • severity:error → テスト失敗で ジョブ失敗(デフォルト設定)
  • severity:warn → テスト失敗でも 警告扱い

このように運用に合わせて挙動を制御することができます。

参考:Source configurations | dbt Developer Hub

外部テーブル向けのメタデータ(external)

DWH(BigQuery/Snowflakeなど)の中に実データを持たず、GCS/S3 など外部ストレージ上のファイル(CSV/Parquet等)を“テーブルのように”参照する仕組みを外部テーブルと言います。
この「外部テーブルであること」や「ファイルの場所/形式」などの情報を、dbt 側(source定義)に書いておけるのが external です。

以下が、GCSに設置されたParquetファイルの外部テーブルの具体例です。

YAML
sources:
  - name: source_name1
    tables:
      - name: events
        external:
          location: "gs://my-bucket/events/*.parquet"
          file_format: "parquet"
          partitions:
            - name: event_date
              data_type: date

参考:external | dbt Developer Hub

鮮度チェック(freshness)

「元データがどれくらい最近更新されたか」を見て、SLA違反を検知する仕組みです。
データ品質(null/重複など)を見るテストとは別で、「更新が止まってないか」をチェックできるのが freshness です。

以下は、イベントテーブルの「event_at(イベント時間)」を起点に、6時間更新されていなければ警告、12時間更新されていなければエラーが出るようにした具体例です。

YAML
sources:
  - name: source_name1
    database: project_id
    schema: ec1
    tables:
      - name: events
        columns:
          - name: event_name
        loaded_at_field: event_at
        freshness:
          warn_after: {count: 6, period: hour}
          error_after: {count: 12, period: hour}

参考:freshness | dbt Developer Hub


まとめ

今回はdbtのsourceについて調べてみました。
ソースを宣言しておくと「dbtの入力データはこれ」と明示でき、依存関係・テスト・鮮度チェックを管理しやすくなるのがポイントでした。

ご紹介した機能もざっくりとした説明となっているので、みなさんも勉強するときは公式リファレンスを見てみてください!

dbt公式リファレンス:About References | dbt Developer Hub

今後も勉強した内容を発信していこうと思います!
では、お楽しみに〜