dbt: comportement précis de la hiérarchie des configurations dans dbt

  1. 🔧 Le comportement hiérarchique de schema
  2. 🧠 Ce que signifie schema: null
  3. ✅ Exemple concret

🧠 1. La hiérarchie de configuration dans dbt

dbt applique les configurations selon une cascade hiérarchique, du plus général vers le plus spécifique :

dbt_project.yml (global)
   ↓
Package-level (si modèle vient d'un package externe)
   ↓
Dossier (dans dbt_project.yml)
   ↓
Fichier modèle .sql (config())
   ↓
Fichier .yml (configurations par modèle)

👉 Le niveau le plus proche du modèle l’emporte sauf si tu précises null, comme on va le voir.


🔍 2. Que fait schema: null dans un modèle ?

Quand tu écris dans un modèle :

{{ config(schema = null) }}

👉 Cela ne veut pas dire “aucun schema”.

Au contraire, cela signifie :

❗ “Ne pas écraser la configuration de schema héritée. Laisse celle du niveau supérieur s’appliquer.”

C’est une manière de ne rien spécifier à ce niveau-là, pour que dbt remonte dans la hiérarchie et prenne la valeur définie au-dessus (souvent au niveau du package ou projet).


📦 3. Exemple concret

Situation :

  • Tu installes un package externe (dbt_utils, my_shared_models)
  • Ce package définit : schema: shared_layer

Dans le packages/my_shared_models/dbt_project.yml :

models:
  my_shared_models:
    +schema: shared_layer

Dans ton projet principal :

Tu surcharges un modèle du package :

-- models/overrides/my_shared_model.sql

{{ config(
    schema = null  -- On ne veut pas écraser le schéma du package
) }}

SELECT * FROM {{ ref('my_shared_models', 'some_model') }}

✅ Résultat : le modèle sera créé dans le schéma shared_layer
💡 Parce que schema=null ne supprime rien, il laisse l’héritage jouer son rôle.


🧾 Résumé du comportement

Configuration dans le modèleRésultat final
schema = "mon_schema"Prend le schéma "mon_schema"
schema = nullHérite du schéma défini plus haut (dossier, package, projet)
Aucun schema du toutIdem : héritage classique

✅ Pourquoi c’est utile ?

BesoinCe que schema: null permet
Ne pas casser une logique de schéma partagée✔️
Surcharger un modèle sans modifier son schéma✔️
Garder une organisation claire des schémas par domaine/package✔️

Exemple

  • ✅ Plusieurs dossiers (staging, intermediate, marts, sandbox)
  • ✅ Un schéma spécifique par dossier (raw_zone, transformed_zone, analytics, etc.)
  • ✅ Des modèles qui héritent (schema: null)
  • ✅ Des modèles qui écrasent (schema: "custom_zone")

🧾 Fichier dbt_project.yml

name: mon_projet_dbt
version: '1.0'
config-version: 2

profile: mon_profil

model-paths: ["models"]
target-path: "target"
clean-targets: ["target", "dbt_modules"]

models:
  mon_projet_dbt:
    staging:
      +schema: raw_zone
      +materialized: view
    intermediate:
      +schema: transformed_zone
      +materialized: ephemeral
    marts:
      +schema: analytics
      +materialized: table
    sandbox:
      +schema: null  # ne définit rien → héritera du niveau supérieur (ou par défaut)

📁 Arborescence des modèles

models/
├── staging/
│   └── stg_clients.sql
├── intermediate/
│   └── int_clients.sql
├── marts/
│   └── mart_clients.sql
├── sandbox/
│   ├── mart_clients_custom.sql
│   └── mart_clients_override.sql

🧱 Modèles avec comportements différents

✅ 1. Modèle qui hérite du dossier

-- models/sandbox/mart_clients_custom.sql

{{ config(materialized='table', schema=null) }}

SELECT *
FROM {{ ref('mart_clients') }}

➡️ Ici, schema: null signifie :
“je ne définis pas de schéma ici, utilise ce qui vient d’au-dessus.”
Mais comme sandbox a +schema: null, dbt utilisera le default_schema (souvent dbt_<user>), sauf si défini ailleurs dans le profil.


✅ 2. Modèle qui écrase la config

-- models/sandbox/mart_clients_override.sql

{{ config(materialized='table', schema='custom_zone') }}

SELECT *
FROM {{ ref('mart_clients') }}

➡️ Ici, le schéma utilisé sera custom_zone, peu importe ce que dit le dossier, le projet ou le profil.


✅ 3. Modèles classiques dans les dossiers définis

-- models/staging/stg_clients.sql
SELECT * FROM {{ source('crm', 'clients') }}

-- models/intermediate/int_clients.sql
SELECT * FROM {{ ref('stg_clients') }}

-- models/marts/mart_clients.sql
SELECT * FROM {{ ref('int_clients') }}
FichierSchéma utiliséPourquoi
stg_clients.sqlraw_zonehérite du dossier staging/
int_clients.sqltransformed_zonehérite de intermediate/
mart_clients.sqlanalyticshérite de marts/
mart_clients_custom.sqldbt_user (par défaut)schema: null + dossier sandbox/ sans +schema
mart_clients_override.sqlcustom_zoneschema défini explicitement dans le fichier

Leave a Reply

Your email address will not be published. Required fields are marked *