ServicesÀ proposNotesContact Me contacter →
EN FR
Note

Le garde full_refresh: false dans dbt

Quand et pourquoi définir full_refresh: false sur les modèles incrémentaux dbt — prévenir les reconstructions accidentelles de plusieurs heures tout en gardant les rafraîchissements complets intentionnels possibles.

Planté
dbtincremental processingdata engineering

La config full_refresh: false empêche dbt run --full-refresh de déclencher une reconstruction complète sur les grands modèles incrémentaux — des milliards de lignes retraitées, des heures de calcul, une facture BigQuery de plusieurs centaines d’euros ou un pic de crédits Snowflake — tout en gardant les rafraîchissements complets intentionnels possibles via un override explicite.

Comment ça fonctionne

Ajoutez full_refresh=false au bloc de config de votre modèle :

{{ config(
materialized='incremental',
unique_key='event_id',
incremental_strategy='merge',
full_refresh=false
) }}

Avec ce paramètre, exécuter dbt run --full-refresh --select my_model se comporte de la même façon qu’une exécution incrémentale normale. Le flag --full-refresh est silencieusement ignoré pour ce modèle.

Pour déclencher un rafraîchissement complet lorsqu’il est nécessaire, la config au niveau du modèle doit être temporairement supprimée ou remplacée — ce qui fait de la reconstruction une action délibérée et explicite plutôt que l’effet secondaire d’une commande plus large.

Quand l’utiliser

full_refresh: false est approprié pour :

Les très grandes tables où le rafraîchissement complet prend des heures. Une table de faits avec 5 ans de données d’événements pourrait prendre 6+ heures pour être entièrement reconstruite. Ce n’est pas quelque chose que vous voulez qu’il se passe parce que quelqu’un a exécuté dbt run --full-refresh sur l’ensemble du projet sans réaliser que ce modèle était inclus.

Les tables avec un coût de calcul significatif par reconstruction. Si un rafraîchissement complet coûte 500 € en calcul BigQuery, ajouter full_refresh: false force cette décision à être consciente plutôt qu’un effet secondaire d’une commande plus large.

Les modèles en aval de sources de données externes. Si votre modèle incrémental lit depuis une API coûteuse ou une source avec une disponibilité historique limitée, un rafraîchissement complet pourrait même ne pas être possible — et s’il s’exécute, il peut échouer ou produire des données incomplètes.

C’est moins utile pour les petits modèles incrémentaux où un rafraîchissement complet est rapide et peu coûteux. Le coût de complexité de la gestion du garde n’en vaut pas la peine si une reconstruction prend 5 minutes.

Le compromis : la dérive s’accumule sans rafraîchissements complets

full_refresh: false résout les reconstructions accidentelles, mais ne résout pas le problème sous-jacent que les modèles incrémentaux dérivent de la vérité source au fil du temps.

Chaque fenêtre de rétroactivité a une limite. Les enregistrements qui arrivent après la fermeture de la fenêtre sont manqués de façon permanente. Les systèmes externes ont des pannes qui retardent les données de semaines. Les pipelines CDC laissent parfois tomber des événements. Aucun de ces cas n’est détecté par une exécution incrémentale quotidienne, quelle que soit la qualité de la configuration de la fenêtre.

Le rafraîchissement complet est le filet de sécurité qui remet à zéro la dérive accumulée. Si vous empêchez tous les rafraîchissements complets avec full_refresh: false, la dérive s’accumule indéfiniment. Le modèle s’éloigne progressivement de ce qu’une reconstruction correcte produirait.

La bonne approche est une stratégie en couches :

  1. Exécutions incrémentales quotidiennes capturent les données récentes, y compris les arrivées tardives dans la fenêtre de rétroactivité
  2. Rafraîchissements complets périodiques remettent à zéro la dérive — hebdomadaires ou mensuels selon votre tolérance et la taille de la table
  3. Rafraîchissement complet à la demande après des problèmes de pipeline connus, des pannes du système source ou des changements de schéma significatifs

Avec full_refresh: false, les rafraîchissements périodiques et à la demande se produisent encore — ils nécessitent simplement une action explicite plutôt que de pouvoir être déclenchés accidentellement.

Comment déclencher réellement un rafraîchissement complet quand vous en avez besoin

Puisque full_refresh: false ignore le flag CLI, vous avez deux options pour forcer une reconstruction :

Option 1 : modifier temporairement la config du modèle. Changez full_refresh=false en full_refresh=true, exécutez le rafraîchissement complet, puis revenez en arrière. C’est explicite et laisse un historique git de la reconstruction intentionnelle.

Option 2 : utiliser un override de variable au niveau du projet. Certaines équipes mettent en place une approche pilotée par variable :

{{ config(
materialized='incremental',
unique_key='event_id',
full_refresh=false if var('protect_full_refresh', true) else true
) }}

Puis exécutez les rafraîchissements complets avec :

Terminal window
dbt run --full-refresh --select my_model --vars '{"protect_full_refresh": false}'

Cela maintient le garde en place par défaut mais permet un override sans toucher au fichier modèle. C’est plus cérémonieux que l’option 1, mais vous permet de reconstruire sans modification de code — utile dans les environnements CI/CD où les modifications de code déclenchent des workflows de revue.

Définition au niveau du projet

Si vous avez de nombreux grands modèles que vous souhaitez protéger, vous pouvez définir le comportement par défaut au niveau du projet ou du dossier dans dbt_project.yml plutôt que sur chaque modèle :

models:
my_project:
mart:
+full_refresh: false

Cela applique full_refresh: false à tous les modèles dans le dossier mart. Les modèles individuels peuvent le remplacer si nécessaire. Cette approche fait de la protection une politique à l’échelle du projet plutôt qu’une décision par modèle, ce qui est plus facile à maintenir mais nécessite l’adhésion de l’équipe à la politique.

Relation avec le filet de sécurité du rafraîchissement complet

Aucune fenêtre de rétroactivité ne capture tout. Un enregistrement avec un horodatage d’événement vieux de 6 mois qui arrive aujourd’hui sera manqué par tout taille de fenêtre pratique. C’est attendu — le modèle incrémental est une optimisation, pas une garantie de cohérence parfaite.

Le rafraîchissement complet périodique est ce qui comble cet écart. Mais si la reconstruction prend 6 heures et coûte des centaines d’euros, les équipes arrêtent de l’exécuter. Le modèle dérive davantage, l’écart entre l’incrémental et la vérité source s’élargit, et quelqu’un finit par remarquer que les chiffres ne correspondent pas.

full_refresh: false résout le problème de reconstruction accidentelle. Les rafraîchissements complets planifiés — peut-être via un job dbt séparé qui s’exécute chaque semaine le samedi — résolvent le problème de dérive. Ensemble, ils forment le fondement opérationnel d’un grand modèle incrémental qui reste fiable au fil du temps.

Pour les tables où même un rafraîchissement complet hebdomadaire est impraticable en raison de la taille, le pattern de comparaison audit_helper (décrit dans testing late-arriving data) vous permet de quantifier la dérive et de prendre une décision éclairée quant au moment où une reconstruction vaut le coût.