大量データの日次更新で全表を作り直すのは非現実的です。dbt の insert_overwrite 戦略は、影響のあるパーティションだけを丸ごと置き換え、他のパーティションをそのまま保つことで、更新コストとリスクを抑えます。
ただし、この戦略はアダプタ依存で挙動や前提が異なります。試験対策では「どのアダプタで使え、どんな前提が必要か」を確実に押さえ、実務では「どのパーティションを洗替えるか」を明示的に制御することが重要です。
dbt の incremental materialization における insert_overwrite は、指定したパーティションのみを新しい結果で置き換える更新戦略です。上流で当日または一部期間のデータが差し替わるケースに向いており、全表再作成より高速・低コストに収まります。
重要なのは「置き換え対象パーティションを、SELECT の結果として明示的に限定する」点です。モデルのクエリが返すパーティションだけが洗替え対象になるため、is_incremental() ブロックで期間やキーを絞り込みます。
dbt モデル設定の最小例(概念)
{{ config(
materialized='incremental',
incremental_strategy='insert_overwrite',
partition_by={'field': 'ds', 'data_type': 'date'}
) }}
with src as (
select * from {{ ref('stg_events') }}
)
select
cast(event_time as date) as ds,
user_id,
count(*) as events
from src
{% if is_incremental() %}
where cast(event_time as date) >= current_date() -- 例: 当日パーティションのみ
{% endif %}
group by 1,2insert_overwrite はアダプタ依存の戦略です。公式ドキュメントの対象アダプタでのみ安定利用を想定してください。少なくとも BigQuery と Spark/Databricks では、パーティション化テーブルを前提とした INSERT OVERWRITE 振る舞いが利用可能です(詳細は dbt Docs を参照)。
Databricks/Spark 環境では、パーティション上書きの粒度制御に関わるセッション設定(dynamic partition overwrite)を適切に有効化します。BigQuery はクエリで返すパーティションが上書き対象となり、DML 単位で原子的に反映されます。
| アダプタ | dbt での insert_overwrite 対応 | 必須前提(パーティション等) | 原子的保証 |
|---|---|---|---|
| BigQuery | 対応あり | partition_by が必須(date/datetime/timestamp ベースが一般的) | ステートメント単位で原子的 |
| Databricks/Spark(Delta 推奨) | 対応あり | partition_by が必須。dynamic partition overwrite を推奨 | Delta の ACID により原子的 |
| Snowflake | 原則未対応(dbt の専用戦略として) | MERGE または delete+insert 等を利用 | MERGE はトランザクション内で原子的 |
| Redshift | 未対応 | 代替として MERGE/CTE ベースの upsert | トランザクション制御に依存 |
Databricks/Spark での dynamic partition overwrite 有効化例
{{ config(
pre_hook=[
"SET spark.sql.sources.partitionOverwriteMode=dynamic"
]
) }}洗替え対象をどう決めるかが設計の核心です。多くのケースでは、上流取り込みの到着範囲(例: 当日分、直近 N 日、あるいは変更を検知したキーに紐づく日付)を根拠にパーティションを特定します。
SELECT が返す行のパーティションだけが置換対象となるため、is_incremental() 節で対象期間を限定し、同じジョブを再実行しても同一結果が得られるように重複排除・集約を含むロジックを組み込みます。
洗替え対象パーティションの流れ(概念図)
変更検知で対象パーティションを限定するクエリ断片(概念)
with src as (
select * from {{ ref('stg_orders') }}
),
changed as (
-- 上流到着ベースで対象パーティションを限定
select distinct cast(updated_at as date) as ds
from src
{% if is_incremental() %}
where _ingested_at >= {{ var('low_watermark', "timestamp_sub(current_timestamp(), interval 1 day)") }}
{% endif %}
)
select /* 対象 ds のみ返すことで、その ds が洗替え対象になる */
cast(order_date as date) as ds,
customer_id,
sum(amount) as revenue
from src
where cast(order_date as date) in (select ds from changed)
group by 1,2BigQuery では INSERT OVERWRITE DML とパーティション化テーブルの組み合わせにより、クエリが返したパーティションのみが原子的に置換されます。dbt 側では partition_by を設定し、is_incremental() 内で対象期間を限定します。
クラスタリングは任意ですが、スキャン効率のため partition_by と組み合わせて設計するのが無難です。長期のバックフィルでは期間をチャンクに分割して複数回に分けるのが実務的です。
dbt モデル例(BigQuery、日次パーティションを洗替え)
{{ config(
materialized='incremental',
incremental_strategy='insert_overwrite',
partition_by={'field': 'ds', 'data_type': 'date'},
cluster_by=['user_id']
) }}
with src as (
select * from {{ ref('stg_events') }}
),
changed as (
-- 上流の到着基準で対象 ds を限定
select distinct cast(event_time as date) as ds
from src
{% if is_incremental() %}
where _ingested_at >= {{ var('low_watermark', "timestamp_sub(current_timestamp(), interval 1 day)") }}
{% endif %}
)
select
cast(event_time as date) as ds,
user_id,
count(*) as events
from src
where cast(event_time as date) in (select ds from changed)
group by 1,2Databricks(Spark)では、Delta Lake の ACID により INSERT OVERWRITE の原子的置換が可能です。dynamic partition overwrite を有効にすると、書き出したパーティションのみが置換され、他のパーティションは不変のまま残ります。
クラスタやジョブのスコープで spark.sql.sources.partitionOverwriteMode=dynamic を設定するのが安全です。dbt では pre_hook を使ってセッション設定する方法もよく用いられます。
dbt モデル例(Databricks/Delta、動的パーティション洗替え)
{{ config(
materialized='incremental',
incremental_strategy='insert_overwrite',
partition_by=['ds'],
file_format='delta',
pre_hook=[
"SET spark.sql.sources.partitionOverwriteMode=dynamic"
]
) }}
with src as (
select * from {{ ref('stg_events') }}
),
changed as (
-- 直近 1 日の到着で変動した ds のみ
select distinct cast(event_time as date) as ds
from src
{% if is_incremental() %}
where load_date >= date_add(current_date(), -1)
{% endif %}
)
select
cast(event_time as date) as ds,
user_id,
count(*) as events
from src
where cast(event_time as date) in (select ds from changed)
group by 1,2運用では、広すぎる洗替えによるコスト・ロック増大を避けるため、最大期間のガードレールや、上限を超えた場合に失敗させるプリチェックを用意します。監視では、更新対象パーティションの件数・範囲、ジョブの所要時間、スキップ検知を記録します。
試験対策としては、次を押さえてください。1) insert_overwrite はアダプタ依存であり、partition_by が必須、2) 上書き対象は SELECT が返すパーティションに限られる、3) Databricks では dynamic partition overwrite の設定が重要、4) Snowflake 等では MERGE を使うのが一般的。
変数を使ったバックフィル(CLI とモデル側の連携)
-- 実行例(7 日分バックフィル)
-- dbt run --select fact_events --vars "start_date: 2026-04-10, end_date: 2026-04-16"
-- モデル側の is_incremental() フィルタ(アダプタ共通の概念例)
{% if is_incremental() %}
where ds between {{ var('start_date', 'current_date()') }} and {{ var('end_date', 'current_date()') }}
{% endif %}Analytics Engineer
問題 1
Databricks(Delta)で日次パーティション ds のみを洗替えたい。dbt モデルの更新で、影響のある ds だけを原子的に置き換え、他のパーティションには触れない構成として最も適切なのはどれか。
正解: A
Databricks/Delta でパーティション単位の置換を安全に行うには、dbt の insert_overwrite 戦略とパーティション化の併用が前提。さらに dynamic partition overwrite を有効化して、返却したパーティションだけを置換する。append は古い行を残すため洗替えにならず、merge はパーティション単位の丸ごと置換が目的のケースでは不要な行粒度の突合が発生しうる。
Snowflake でも insert_overwrite は使えますか?
dbt の insert_overwrite 戦略は主に BigQuery と Spark/Databricks での利用が前提です。Snowflake では通常 MERGE(または delete+insert)で同等の要件を満たします。アダプタの対応状況は dbt 公式ドキュメントを確認してください。
対象パーティションの広がりをどう抑制すべきですか?
is_incremental() 節で日付範囲や変更キーを用いて厳密に限定し、最大パーティション数の上限チェックを pre_hook で行うと安全です。想定外に広い場合は失敗させ、オペレータ確認を挟む運用が有効です。
重複や順序入れ替えが起こるソースに対しても安全ですか?
安全にするには、洗替え対象パーティション内で決定版を生成するロジック(重複排除、最新優先のウィンドウ関数、集約)を必ず含めてください。insert_overwrite 自体は置換の器であり、正しさは SELECT の内容に依存します。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
dbt Model の基礎: SQL で定義する変換の最小単位
Analytics Engineer 向けに、dbt Model の定義、マテリアライゼーション、依存関係、インクリメン...
dbt Analytics Engineer 試験ガイド: 出題範囲・配点・申込の実務視点
dbt Analytics Engineer 認定の出題範囲、配点の考え方、申込から受験までの流れを、公式ドキュメントの...
dbt Cloud と dbt Core の違いと選び方:Analytics Engineer 試験に効く要点
dbt Cloud と dbt Core の機能差を、実務と資格対策の両面から整理。スケジューリング、IDE、RBAC、...
dbt プロジェクト構造ガイド: models / seeds / macros の実務レイアウト
Analytics Engineer 向けに、dbt プロジェクトのディレクトリ構造と命名規約、dbt_project....
dbt_project.yml の読み方:主要設定と命名を最短で掴む
dbt_project.yml の必須キー、命名解決(database.schema.identifier)、設定優先度...