3
0

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初学者が学んだポイント

Last updated at Posted at 2025-12-24

概要

社内のdbt基盤で新規テーブルを作成する機会があり、dbt初挑戦しました。
そこで学んだポイントを4つ紹介します。

1. dbtのレイヤー構成を理解する

dbtのレイヤー構成

dbtではデータを段階的に加工していく「レイヤー構成」が推奨されています。
代表的な構成は以下の通りです。

レイヤー 役割
source 生データの参照元を定義
staging sourceを軽く整形(カラム名変更、型変換など)
marts 最終的な分析用テーブル

詳細:How we structure our dbt projects | dbt Best Practices

ZOZOで実際に採用しているレイヤーについては以下をご参照ください。

sourceから順番に定義していく

各レイヤーを作成する際は、最上流となるテーブルを「source」として定義する必要があります。

# models/sources/sample_xxx.yml
sources:
  - name: my_source
    database: my-project
    schema: my_dataset
    tables:
      - name: my_table

私はついこのレイヤー構造を忘れてダミーデータ作成に失敗しました。
「大元の参照先がないと下流のレイヤーは作れない」という当たり前のことですが...

sourceを定義すると、SQL内で{{ source('my_source', 'my_table') }}のように参照でき、dbt docsでリネージ(データの依存関係)が自動で可視化されます。

詳細:Sources | dbt Docs

2. CTEの書き方にはdbt流のお作法がある

CTEとは

CTE(Common Table Expression)は、WITH句を使って一時的な結果セットに名前を付ける機能です。
サブクエリを変数のように扱えるため、複雑なクエリを読みやすく整理できます。

-- CTEを使わない場合(サブクエリのネスト)
select *
from (
    select *
    from (
        select * from my_table where is_deleted = false
    ) as filtered
    where event_date = '2025-01-01'
) as dated

-- CTEを使う場合
with filtered as (
    select * from my_table where is_deleted = false
),
dated as (
    select * from filtered where event_date = '2025-01-01'
)
select * from dated

CTEを使うことで、処理の流れが上から下へ自然に読めるようになります。

詳細:Getting started with CTEs | dbt Blog

dbt流のCTE構成

dbtでは「dbtonic」と呼ばれる書き方が推奨されています。
CTEの構成は以下の3つに分けるのがベストプラクティスです。

CTE種別 役割
import CTE sourceやrefで外部テーブルを取得
logical CTE フィルタリングや変換などのビジネスロジック
final CTE 最終的な出力を整形
-- import CTE
with source as (
    select * from {{ source('my_source', 'my_table') }}
),

-- logical CTE  
filtered as (
    select * from source where is_deleted = false
),

-- final CTE
final as (
    select
        user_id,
        event_timestamp,
        content_id
    from filtered
)

select * from final

最終SELECTはカラムを列挙せずにselect * にするところもポイントです。
この構成に従うことで、データ取得、加工、出力の流れが一目で分かります。

詳細:How we style our dbt projects | dbt Best Practices

3. dbt testでデータ品質を担保する

dbtではYAMLでテストを宣言的に定義できます。
テストはdbt buildやdbt test実行時に自動でチェックされます。

# models/marts/sample_test_xxx.yml
models:
  - name: sample_test_xxx
    columns:
      - name: key
        tests:
          - unique
          - not_null
      - name: id
        tests:
          - not_null
          - relationships:
              to: ref('dim_users_id')
              field: id
      - name: name
        tests:
          - accepted_values:
              values: ['piyo', 'hoge']

代表的なテストパターンは以下:

テスト 用途
unique 値が一意であることを確認
not_null NULLがないことを確認
accepted_values 許可された値のみであることを確認
relationships 他テーブルとの参照整合性を確認

詳細:Data tests | dbt Docs

4. dbt testのWARN/ERROR調査方法を把握しておく

調査手順の例:

  1. コンパイル済みSQLを取得
  2. SQLを直接実行
  3. 該当レコードの詳細を確認

コンパイル済みSQLは、Elementaryダッシュボード等の監視ツールから取得できます。
ローカル環境であればdbt compile実行後にtarget/compiled/配下に生成されます。

私のケースでは、Elementaryダッシュボードから該当SQLを取得し、マスタテーブルの更新タイミング差(データ遅延)が原因でWARNが発生したことを特定しました。

詳細:


dbt独自のお作法に関しては学習コストがありますが、かなり勉強になりました。

以上です。
どなたかのお役に立てれば幸いです。

参考

ZOZOの詳細情報

3
0
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
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?