dbt

dbt の delete+insert 戦略を使った再構築アプローチ

2026-04-19
NicheeLab編集部

delete+insert は、対象テーブルから該当キーの行を一旦削除し、新しい行を挿入して整合性を保つ増分戦略です。MERGE が最適でない、またはサポートが限定的な環境で堅実に動作します。

本記事では、公式ドキュメントの前提に沿い(dbt docs: Incremental models と各アダプタの戦略)、バージョン差異に依存しにくいベーシックな設計・運用パターンに絞って、実務と試験(Analytics Engineer)双方で役立つ視点を提供します。

delete+insert 戦略の要点と再構築の考え方

delete+insert は、ユニークキーで対象行を特定し、古い行を削除して新しい行を挿入することで、結果整合性を保つ増分アップサートを実現します。MERGE のような単一文でのアップサートが使えない、あるいは運用上の理由で避けたい場合に有効です。

再構築アプローチとしては、対象キー範囲を明示しつつ部分的に作り直す、あるいは問題発生時に該当キーの削除と再投入で巻き戻しやすい、という利点があります。トランザクション分離やロックの特性はアダプタ依存のため、ジョブ並列度とテーブル設計(クラスタリング、パーティション)を合わせて検討します。

  • 前提: materialized=incremental、unique_key の指定が基本
  • データの差分抽出は is_incremental() で制御
  • 失敗時のリカバリ: 同一キーを再削除→再挿入で可逆性が高い
  • 適用例: Redshift の歴史的実装、Merge 制約のある環境、分割再構築を重視するパイプライン
戦略要件/依存強み・向き不向き
delete+insertunique_key 必須。DELETE/INSERT サポート。再実行が簡単。I/O は多め。キーの選定が命。
mergeMERGE DML/Delta MERGE などのアダプタ機能。高速かつ一貫したアップサート。機能未対応環境では不可。
insert_overwriteパーティション・クラスタの明示的制御。パーティション単位の置換が速い。設計要件が厳格。

delete+insert の処理フロー(再構築志向)

増分ソース (新規・更新分)一時/ソースCTE: new_rowsunique_key 集合を抽出DELETE FROM target_table WHERE unique_key IN (...)INSERT INTO target_table (new_rows)

最小構成の dbt 増分モデル(delete+insert)

with source as (
  select * from {{ ref('stg_orders') }}
  {% if is_incremental() %}
    where updated_at >= (select coalesce(max(updated_at), '1900-01-01') from {{ this }})
  {% endif %}
),

new_rows as (
  select
    order_id as id,
    customer_id,
    status,
    updated_at
  from source
)

select * from new_rows

-- model config (at top of file, or via config block)
-- {{ config(
--   materialized='incremental',
--   incremental_strategy='delete+insert',
--   unique_key='id'
-- ) }}

要求事項と前提条件:unique_key と差分制御

delete+insert は unique_key がないと成立しません。キーの重複は削除対象の不確定性を生み、誤削除や重複挿入の温床になります。キーは論理一意(複合可)で、ターゲットでもインデックスやクラスタリングの観点から実体化しておくのが実務的です。

差分抽出は is_incremental() で制御します。updated_at やロード境界列で範囲を絞り、delete 範囲と一致するキー集合を生成します。タイムスタンプの遅延着地(late arriving)を考慮し、やや広めのウィンドウを取るか、再実行ポリシーを明確化します。

  • unique_key は単一・複合いずれも可、NULL 禁止設計が望ましい
  • 差分条件は更新日時、増分フラグ、ハッシュ変化検出などが現実的
  • 検証用のユニークテストと非NULLテストを dbt tests で併用
  • ターゲット側のキー検索を速くするためのクラスタ/ソート/インデックス設計
項目推奨理由
unique_key論理一意・NULL なしDELETE 範囲を正しく決定するため
差分列updated_at + 余裕窓遅延到着の吸収・再実行で安定
制約/物理設計クラスタ/パーティション/索引DELETE 対象探索と INSERT 性能の両立

差分抽出とキー集合の対応

source rowsnew_rowsfilter by is_incremental()unique_key 集合derive keys差分抽出とキー集合の対応

複合キーとウィンドウ付与の例

{{ config(
  materialized='incremental',
  incremental_strategy='delete+insert',
  unique_key=['id','effective_date']
) }}

with src as (
  select * from {{ ref('stg_line_items') }}
  {% if is_incremental() %}
    where updated_at >= dateadd(day, -1, (select coalesce(max(updated_at),'1900-01-01') from {{ this }}))
  {% endif %}
)
select id, effective_date, qty, price, updated_at from src

実装パターン:モデル定義と構成の切り分け

コンフィグはモデルファイル先頭の config ブロック、または dbt_project.yml の models セクションで管理します。環境差(本番・検証)で戦略を切り替える場合は、vars や target.name を条件に分けると管理が楽です。

一部アダプタでは MERGE がデフォルト化される場合がありますが、delete+insert を明示すれば当該戦略が用いられます。サポート可否や既定挙動はアダプタの公式ドキュメントで確認してください。

  • モデル内で戦略・キーを明示し、テストで一貫性を担保
  • 環境別で incremental_strategy を変えると検証しやすい
  • dbt run-operation でメンテ用スクリプトを補助的に活用
構成箇所使い分け注意点
model内 configモデル固有の要件を即記述設定過多だと横断管理が難しい
dbt_project.ymlパターンの一括適用例外モデルを override で上書き
環境変数/vars環境ごとに戦略切替分岐が複雑化しすぎないように

環境別の戦略切替イメージ

target=devdelete+insert 明示target=prod本番でも同戦略 or MERGE環境別の戦略切替イメージ

dbt_project.yml での既定戦略と上書き

models:
  project_name:
    +materialized: incremental
    +incremental_strategy: delete+insert
    +unique_key: id
    marts:
      orders:
        +incremental_strategy: delete+insert  # explicit
        +unique_key: [id, effective_date]

パフォーマンスと運用上の落とし穴

delete+insert は I/O が増えがちです。削除対象の探索を速くするため、ターゲットテーブルのクラスタリング(Snowflake)、クラスタ/ソートキー(Redshift)、クラスタリング/パーティショニング(BigQuery)、Z-ORDER やクラスター化(Databricks Delta)など、プラットフォーム固有の最適化を組み合わせます。

バルク DELETE のロック影響やタイムトラベル/保持期間のストレージ増分にも注意します。スケジュールをずらして同一キー範囲の併走を避ける、ジョブ単位でキー範囲をシャーディングするなど、運用での工夫が効きます。

  • キー列に基づくクラスタリング・分割で DELETE 範囲のスキャンを縮小
  • 挿入は COPY/INSERT バッチ化(アダプタ依存)で効率化
  • ジョブ並列は同一キー競合を避ける(悲観/楽観ロック差に留意)
  • 保持期間や自動クラスタリングのコスト影響を事前見積もり
最適化項目期待効果注意点
クラスタ/分割設計DELETE と INSERT のスキャン削減過剰分割は小ファイル化・オーバーヘッド
バッチサイズ調整コミット回数削減・スループット向上長大トランザクションの失敗リスク
キー範囲のシャーディング同時実行性向上抜け漏れ防止のキー範囲管理が必要

キーに沿ったクラスタリングでスキャン最小化

Beforerandom distributionDELETE scans wideAfterclustered by unique_keyDELETE scans narrowキーに沿ったクラスタリングでスキャン最小化

クラスタリング/分割の設計例(概念)

-- Snowflake 例(概念)
-- create or replace table T cluster by (id);
-- BigQuery 例(概念)
-- partition by date(updated_at) cluster by id
-- Databricks Delta 例(概念)
-- optimize T zorder by (id)

検証と再実行:可逆な再構築の進め方

delete+insert は、失敗時に該当キーの再削除→再挿入で回復しやすいのが強みです。モデル間の依存関係(ref)で下流が参照するタイミングを管理し、テスト(unique、not_null、関数的重複排除)をパイプライン終端で走らせて不整合を早期検出します。

フルリフレッシュ(--full-refresh)は全件再構築の最後の手段です。まずは影響キーの特定と部分再実行(--select model_name)で切り戻しを試み、必要に応じて再実行ウィンドウを一時的に広げて整合性を取り戻します。

  • 失敗の粒度をキー単位に落とし込み、部分再実行で回復
  • 検証テストはユニーク/非NULL/関数的重複で三層に
  • 本番は read-consistent に配慮し、切替タイミングを制御
  • フルリフレッシュはコスト・ロック時間を事前に見積もる
失敗シナリオ挙動推奨対応
INSERT 中断一部のキーが未挿入同一増分で再実行、重複は事前 DELETE で吸収
DELETE 中断古い行が残留次回実行で再度 DELETE→INSERT で解消
差分抽出漏れ更新落ち・欠損ウィンドウ拡大 or 影響キー特定で再実行

失敗時の可逆フロー

Failidentify keysrerun same windowDELETE keysINSERT rowstests pass

部分再実行とフルリフレッシュの使い分け

# 影響モデルのみ再実行
# dbt run --select my_incremental_model

# フルリフレッシュ(最終手段)
# dbt run --full-refresh --select my_incremental_model

試験対策:Analytics Engineer で狙われるポイント

試験では、増分戦略ごとの適用条件の理解、unique_key が delete+insert で必須であること、is_incremental() の使い方、--full-refresh の意味、アダプタ差に対する保守的な判断が問われます。

また、MERGE と delete+insert の違い、insert_overwrite の前提(パーティション置換)を比較で整理できているかが重要です。

  • delete+insert は unique_key が要、差分抽出とテストで堅牢化
  • MERGE は単文アップサートだが、環境依存のため常用は要確認
  • insert_overwrite はパーティション単位の再構築で効率的
  • 失敗時の再実行シナリオとフルリフレッシュの使い分け
テーマキーワードひっかけポイント
増分戦略の選択unique_key / MERGE / overwriteunique_key なしで delete+insert は不可
差分制御is_incremental() / 境界列等号の向き・遅延到着の扱い
再実行--full-refresh / 部分選択フルリフレッシュ濫用によるコスト

戦略間の学習マップ

delete+insertmergeinsert_overwrite要: unique_key要: MERGE対応要: partition設計戦略間の学習マップ

試験で頻出の設定スニペット

{{ config(
  materialized='incremental',
  incremental_strategy='delete+insert',
  unique_key='id'
) }}
{% if is_incremental() %}
  -- 差分条件を忘れない
{% endif %}

問題で確認

Analytics Engineer

問題 1

dbt の増分モデルで delete+insert 戦略を選ぶ主な理由として、最も適切なのはどれか。

  1. MERGE のサポートや運用制約により、行単位での安全な再構築(削除→挿入)を実現したいから
  2. テーブルを常に完全再計算し、集計精度を最大化したいから
  3. パーティションを自動で作成し、常に最新パーティションだけを置換したいから
  4. unique_key を持たないイベントログをそのままアップサートしたいから

正解: A

delete+insert は unique_key を前提に、該当行を削除してから新行を挿入する戦略。MERGE が使えない/避けたい場合でもアップサートを安定提供でき、失敗時の再実行も容易。完全再計算(B)は full-refresh の話、パーティション置換(C)は insert_overwrite、unique_key なし(D)は不適。

よくある質問

delete+insert で unique_key が NULL になる可能性がある列でも使えるか?

推奨されません。NULL が混在すると削除対象が確定できず、重複や残存が発生します。モデル上で coalesce による正規化、または複合キー化で NULL を排除し、dbt の unique / not_null テストで担保してください。

MERGE が使える環境でも delete+insert を選ぶ利点は?

再実行の単純さ(該当キーの再削除→再挿入)や、ロジックの可観測性を重視する場合に向きます。とはいえ、多くの環境では MERGE の方が効率的なことが多く、I/O とロック影響を評価したうえで選択してください。

insert_overwrite と delete+insert はどう使い分ける?

パーティション設計が明確で、置換範囲をパーティション単位で定義できるなら insert_overwrite が高速です。パーティション設計が難しい、またはキー単位の精緻な再構築が必要なら delete+insert を検討します。

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

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.