Blocs de configuration complets pour chaque stratégie incrémentielle, organisés par entrepôt et cas d’usage. Pour la logique de sélection de stratégie, consultez le cadre de décision. Pour les détails des comportements spécifiques à chaque entrepôt, consultez les comportements des stratégies incrémentielles par entrepôt.
Merge avec prédicats incrémentiels (BigQuery / tables volumineuses)
À utiliser quand vous avez besoin de mises à jour au niveau des lignes sur une table qui a dépassé 100 M de lignes. Les incremental_predicates limitent le scan de la table de destination lors du MERGE, ce qui est la clé pour maintenir la viabilité du merge à grande échelle. Consultez les prédicats incrémentiels pour l’explication complète du fonctionnement des deux filtres ensemble.
{{ config( materialized='incremental', unique_key='event_id', incremental_strategy='merge', incremental_predicates=[ "DBT_INTERNAL_DEST.event_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY)" ]) }}
SELECT event_id, event_date, event_name, user_id, event_propertiesFROM {{ ref('base__segment__events') }}{% if is_incremental() %}WHERE event_date >= (SELECT MAX(event_date) - INTERVAL 3 DAY FROM {{ this }}){% endif %}Le filtre is_incremental() couvre 3 jours de données source (une fenêtre de rétroaction pour les enregistrements tardifs). Le prédicat couvre 7 jours côté destination — délibérément plus large pour s’assurer que toutes les correspondances sont trouvées. Un prédicat de destination plus étroit que votre filtre source peut faire rater des correspondances légitimes au merge.
Delete+Insert sur Snowflake
À utiliser quand les tables dépassent 100 M de lignes sur Snowflake. C’est le remplacement standard du merge à grande échelle — 3,4x plus rapide à plus de 500 M de lignes dans les benchmarks de production. Non atomique : si le processus échoue entre la suppression et l’insertion, les enregistrements sont temporairement absents.
{{ config( materialized='incremental', unique_key='order_id', incremental_strategy='delete+insert') }}
SELECT order_id, customer_id, order_date, updated_at, total_amountFROM {{ ref('base__shopify__orders') }}{% if is_incremental() %}WHERE updated_at >= (SELECT MAX(updated_at) - INTERVAL 3 DAY FROM {{ this }}){% endif %}La fenêtre de rétroaction gère les commandes tardives. La unique_key pilote l’étape DELETE — dbt supprime toutes les lignes dans la cible où order_id correspond à une ligne entrante, puis insère le lot complet.
Insert_Overwrite avec partitions statiques (BigQuery)
À utiliser pour les tables de faits partitionnées par le temps sur BigQuery où l’optimisation des coûts est importante. Les listes de partitions statiques sont plus rapides que les dynamiques car BigQuery n’a pas besoin d’une requête de découverte pour déterminer quelles partitions remplacer.
{% set partitions_to_replace = [ 'CURRENT_DATE()', 'DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)', 'DATE_SUB(CURRENT_DATE(), INTERVAL 2 DAY)'] %}
{{ config( materialized='incremental', incremental_strategy='insert_overwrite', partition_by={'field': 'event_date', 'data_type': 'date'}, partitions=partitions_to_replace) }}
SELECT event_id, event_date, event_name, user_id, event_propertiesFROM {{ ref('base__segment__events') }}{% if is_incremental() %}WHERE event_date IN ({{ partitions_to_replace | join(',') }}){% endif %}La config partitions indique à BigQuery exactement quelles partitions remplacer. La clause WHERE is_incremental() filtre la requête source pour correspondre. Les deux listes doivent être alignées — si vous remplacez 3 jours de partitions mais sélectionnez 7 jours de données source, les jours supplémentaires sont du compute gaspillé.
La liste de partitions agit comme une fenêtre de rétroaction intégrée : remplacer aujourd’hui plus les 2 jours précédents capture la plupart des données d’événements tardives. Pour étendre la fenêtre, ajoutez davantage d’entrées à partitions_to_replace.
Ce pattern ne nécessite pas de unique_key car des partitions entières sont remplacées de façon atomique — il n’y a pas de correspondance au niveau des lignes. Les doublons dans la requête source seront propagés dans la partition, donc incluez une déduplication dans votre SELECT si votre source peut avoir des doublons.
Insert_Overwrite avec partitions dynamiques (BigQuery)
À utiliser quand vous ne savez pas à l’avance quelles partitions contiendront de nouvelles données. Plus lent que les partitions statiques car BigQuery exécute d’abord une requête de découverte, mais gère les patterns d’arrivée de données imprévisibles.
{{ config( materialized='incremental', incremental_strategy='insert_overwrite', partition_by={'field': 'event_date', 'data_type': 'date'}) }}
SELECT event_id, event_date, event_name, user_id, event_propertiesFROM {{ ref('base__segment__events') }}{% if is_incremental() %}WHERE event_date >= _dbt_max_partition{% endif %}_dbt_max_partition est une variable de scripting BigQuery, pas du Jinja. Elle est résolue au moment de la requête dans l’entrepôt et contient la valeur de partition maximale dans la table cible. dbt génère un bloc DECLARE/SET qui peuple cette variable avant l’exécution de la requête principale.
Replace_Where sur Databricks
À utiliser pour les mises à jour bornées dans le temps sur Databricks avec Delta Lake. Plus flexible que insert_overwrite car le prédicat peut être n’importe quelle expression, pas seulement une frontière de partition. Atomique.
{{ config( materialized='incremental', incremental_strategy='replace_where', incremental_predicates=["event_date >= CURRENT_DATE - INTERVAL 3 DAY"]) }}
SELECT event_id, event_date, event_name, user_id, event_propertiesFROM {{ ref('base__segment__events') }}WHERE event_date >= CURRENT_DATE - INTERVAL 3 DAYRemarque : pas de bloc is_incremental(). Le filtre source s’applique à chaque exécution (rechargement complet et incrémental). La config incremental_predicates contrôle quelles lignes dans la cible sont remplacées. Sur un rechargement complet, les prédicats sont ignorés et la table entière est reconstruite.
Cela signifie que la requête source retourne toujours seulement 3 jours de données. Sur un rechargement complet, cela construit une table avec seulement 3 jours. Si vous avez besoin que le rechargement complet traite toutes les données historiques, encapsulez le WHERE dans is_incremental() :
{% if is_incremental() %}WHERE event_date >= CURRENT_DATE - INTERVAL 3 DAY{% endif %}Merge avec pattern CDC (Databricks)
À utiliser pour les workloads de Change Data Capture où vous devez propager les insertions, les mises à jour et les suppressions depuis un système source. Les options matched_condition et not_matched_by_source_action spécifiques à Databricks permettent des patterns que d’autres entrepôts nécessitent des macros personnalisées pour implémenter.
{{ config( materialized='incremental', unique_key='customer_id', incremental_strategy='merge', merge_with_schema_evolution=true) }}
SELECT customer_id, customer_name, email, updated_at, is_deletedFROM {{ ref('base__crm__customers') }}{% if is_incremental() %}WHERE updated_at >= (SELECT MAX(updated_at) - INTERVAL 3 DAY FROM {{ this }}){% endif %}QUALIFY ROW_NUMBER() OVER ( PARTITION BY customer_id ORDER BY updated_at DESC) = 1Le paramètre merge_with_schema_evolution=true permet aux nouvelles colonnes de la source de se propager automatiquement vers la cible sans nécessiter de configuration on_schema_change ou d’instructions ALTER TABLE.
La clause QUALIFY assure l’idempotence en dédupliquant avant l’étape de merge.
Choisir votre pattern
| Votre situation | Pattern à utiliser |
|---|---|
| Mises à jour au niveau des lignes, table en croissance, BigQuery | Merge avec prédicats |
| Table volumineuse (100M+), Snowflake | Delete+insert |
| Faits partitionnés par le temps, BigQuery | Insert_overwrite avec partitions statiques |
| Ensemble de partitions inconnu, BigQuery | Insert_overwrite avec partitions dynamiques |
| Mises à jour bornées dans le temps, Databricks | Replace_where |
| CDC avec suppressions, Databricks | Merge avec évolution de schéma |
Pour la logique de décision complète derrière ces choix, consultez le cadre de décision pour les stratégies incrémentielles. Pour les pièges et limitations spécifiques à chaque entrepôt, consultez la note sur les comportements par entrepôt.