dbt

dbt incremental の append 戦略を極める:単純追加パターンの設計・実装・試験対策

2026-04-19
NicheeLab編集部

append は「既存行を一切更新せず、新規行だけを追記する」最速の増分戦略です。イベントログや監査証跡など不変データに最適ですが、設計を誤ると重複や取りこぼしが発生します。

本稿では dbt の安定機能に基づき、実務で安全に使うための最小要件とパターン、そして Analytics Engineer 試験で問われやすい論点をまとめます。

append 戦略の概要と使いどころ

append は、初回は全量作成、2回目以降は is_incremental() ブロックで絞り込んだ新規レコードだけを INSERT します。既存行の更新・削除は一切行いません。

よって、データが実質的に不変(immutable)であるか、もしくはアップサートを不要とする要件でのみ採用すべきです。更新が必要な場合は merge 等の別戦略を選びます。

  • 長所: 最も高速・低コスト。ロックや競合の影響が小さい。
  • 短所: 更新・削除に非対応。重複や遅延到着を自前で防御する必要がある。
  • 前提: 増分境界(ウォーターマーク)となる列の存在(例: created_at, _ingested_at)。
戦略基本動作更新/削除対応主な適用シナリオ
append新規行のみ INSERT不可イベントログ、不変監査証跡、追記型 CDC ストリーム
mergeキー一致は更新/挿入、条件次第で削除可(アダプター依存)ディメンションのアップサート、最新状態の整備
insert_overwriteパーティション単位で上書き限定的(単位内の置換)BigQuery 等での日次/時間分割の再生成

append 戦略のデータフロー(単純追加)

SourceStaging整形/重複前処理Incremental Model (append)Target Table既存行: 不変 / 新規行: 追記

append 戦略の最小構成(イメージ)

{{ config(materialized='incremental', incremental_strategy='append') }}

with src as (
  select * from {{ ref('stg_events') }}
  {% if is_incremental() %}
    -- 新規レコードだけを通すフィルタ(後述で具体例)
  {% endif %}
)
select * from src;

内部動作と要件:is_incremental とウォーターマーク設計

dbt の増分モデルは、初回実行時は is_incremental() が偽のため全量 SELECT が実行され、次回以降は真となり、開発者が書いた WHERE 句で新規行だけを抽出します。append では unique_key は使用されません(指定してもアップサートは行われません)。

最重要はウォーターマーク列の選定です。一般的に単調増加するタイムスタンプ(created_at や _ingested_at)の最大値を {{ this }} 側で参照し、それより新しいソース行のみを取り込みます。遅延到着を考慮してセーフティウィンドウ(例: 2 日巻き戻し)を取るのが実務的です。

  • 必須: 単調増加・欠損が少ない境界列(タイムゾーン一貫性にも注意)
  • 推奨: is_incremental() 内で {{ this }} の max(境界列) を参照
  • 注意: append は既存行更新不可。更新が必要なら merge 戦略へ

ウォーターマーク参照の基本パターン

{{ config(materialized='incremental', incremental_strategy='append') }}

with src as (
  select * from {{ ref('stg_events') }}
  {% if is_incremental() %}
    where created_at > coalesce((select max(created_at) from {{ this }}), '1970-01-01')
  {% endif %}
)
select * from src;

実装テンプレート:append(単純追加)の定石

以下は運用に耐える最小構成例です。on_schema_change の挙動はアダプター依存のため、対応状況を確認のうえ使用してください。サポートされる場合、append_new_columns は新規列を追記し、既存行には NULL を入れます。

ステージングでの事前重複排除と、ターゲット側での境界列フィルタを併用するのが安全です。

  • 新規列の追加可能性が高い場合は on_schema_change の方針を明示
  • ステージングでキー重複を取り除く(ROW_NUMBER 等)
  • ターゲットの列順は明示的に投影(列追加時の不整合回避)

append 戦略の運用テンプレート(Snowflake/Databricks/BigQuery いずれでも概念同じ)

{{ config(
  materialized='incremental',
  incremental_strategy='append',
  on_schema_change='append_new_columns',  -- アダプターがサポートする場合
  tags=['incremental','append']
) }}

with deduped as (
  select
    id,
    created_at,
    payload,
    row_number() over (partition by id, created_at order by _ingested_at desc) as rn
  from {{ ref('stg_events') }}
), src as (
  select id, created_at, payload from deduped where rn = 1
  {% if is_incremental() %}
    -- 2 日巻き戻して遅延到着をカバー(取り込み重複は上流で排除)
    where created_at >= dateadd(day, -2,
      coalesce((select max(created_at) from {{ this }}), '1970-01-01')
    )
  {% endif %}
)
select id, created_at, payload from src;

遅延到着・重複への耐性設計とテスト

append は更新できないため、遅延到着や同一行の再送があると簡単に重複が生じます。これを避けるには、上流での重複排除+セーフティウィンドウの再取り込みを組み合わせます。取り込み窓を広げると再取り込み量は増えますが、重複はステージングで排除できます。

dbt のテストでは、ターゲット表に対して完全一意キーを強制するのではなく、現実的な組み合わせ(例: id, created_at)に一意制約テストをかけるのが有効です。

  • セーフティウィンドウ: dateadd などで最大境界から数日巻き戻し
  • ステージング: row_number で最新レコード 1 件に絞る
  • テスト: 重複の早期検知(unique, not_null)

schema.yml の一意性テスト例(ターゲット)

version: 2
models:
  - name: fct_events_append
    tests: []
    columns:
      - name: id
        tests: [not_null]
      - name: created_at
        tests: [not_null]
    tests:
      - dbt_expectations.expect_compound_columns_to_be_unique:
          column_list: ['id','created_at']

運用:フルリフレッシュ、スケジューリング、スキーマ変更

append では既存行を直せないため、上流起因の欠損・型誤りを是正するときはフルリフレッシュが有効です。--full-refresh は対象モデルを再作成します。

スキーマ変更は on_schema_change のサポート状況に従い設定します。未対応のアダプターではフルリフレッシュで反映させるのが安全です。

  • フルリフレッシュ: 不整合や大量遅延の一括是正に使用
  • スケジューリング: 取り込み窓と上流到着遅延を踏まえた頻度設定
  • 監視: 行数増分、最大 created_at の前進、エラー比率のモニタリング

よく使うコマンド

# 単一モデルを増分実行
 dbt run -s fct_events_append

# タグでバッチ実行
 dbt run -m tag:append

# フルリフレッシュ
 dbt run -s fct_events_append --full-refresh

試験対策:押さえるべき落とし穴と要点

Analytics Engineer 試験では、append の適用条件、is_incremental の役割、unique_key の扱い、フルリフレッシュの意味などの基礎が頻出です。merge との違いを文章で正確に説明できるかを意識してください。

特に「append は既存行を変更しない」「unique_key を指定してもアップサートされない」「遅延到着への対策が必要」という3点はセットで問われやすいです。

  • append は新規 INSERT のみ。更新・削除は不可
  • is_incremental() 内で新規行の定義(ウォーターマーク)を書く
  • unique_key は append では使われない(merge で必要)
  • --full-refresh はテーブルを作り直す動作

誤り例と正解例(コンセプト)

-- 誤り: append で unique_key を当ててもアップサートされない
{{ config(materialized='incremental', incremental_strategy='append', unique_key='id') }}
-- 正解: append では is_incremental() で新規行を定義
{{ config(materialized='incremental', incremental_strategy='append') }}
{% if is_incremental() %}
  where created_at > (select max(created_at) from {{ this }})
{% endif %}

問題で確認

Analytics Engineer

問題 1

dbt の incremental モデルで append 戦略を用いる場合、正しい記述はどれか。

  1. unique_key を指定すれば既存行は更新され、重複は自動的に解消される。
  2. is_incremental() は dbt が自動で適切な WHERE 句を挿入するため、開発者が条件を書く必要はない。
  3. append は新規行のみを INSERT し、既存行の更新や削除は行わない。遅延到着への対策はモデル側で設計する必要がある。
  4. --full-refresh は append モデルに対して無効であり、常に増分のみが実行される。

正解: C

append は新規行を追記するのみでアップサートはしません。unique_key は使用されず、遅延到着や重複への対策は is_incremental() の条件やステージングで設計します。--full-refresh は有効で、テーブルを作り直します。

よくある質問

append 戦略で unique_key を設定するとどうなりますか?

append では unique_key は使用されません。既存行の更新や重複解消は行われないため、アップサートが必要な場合は merge 戦略を選択してください。

遅延到着データはどう扱えば安全ですか?

is_incremental() の WHERE で最大境界から数日分巻き戻すセーフティウィンドウを設け、ステージングで row_number などにより重複排除してからターゲットへ append するのが実務的です。

スキーマ変更(列追加)が起きたらどうなりますか?

アダプターが on_schema_change=append_new_columns などをサポートしていれば、新規列を追加できます。未対応または複雑な変更時は --full-refresh で再作成するのが安全です。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
dbt

dbt Model の基礎: SQL で定義する変換の最小単位

Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...

dbt

dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点

dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...

dbt

dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点

dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...

dbt

dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト

Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....

dbt

dbt_project.yml の読み方:主要設定と命名を最短で掴む

dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...

dbtの記事一覧 (100件)
© 2026 NicheeLab All rights reserved.