📅 ✍️ difTech

Depuis que dbt (data build tool) a émergé comme standard de facto de la transformation de données, combiné à la puissance serverless de BigQuery, nous assistons à une véritable révolution dans la façon dont les équipes data travaillent. Après cinq ans à déployer et maintenir des projets dbt+BigQuery en production — de la startup de 10 personnes à la multinationale de plusieurs milliers d’employés — voici ce que nous avons appris.

Pourquoi dbt a changé le métier de data analyst et engineer

Avant dbt, la transformation de données ressemblait à ceci : des scripts SQL éparpillés dans des dossiers mal nommés, des procédures stockées impossibles à tester, des dépendances entre tables documentées nulle part, et un seul Data Engineer qui “savait” comment tout fonctionnait. Le bus factor à son paroxysme.

dbt a renversé ce modèle en appliquant les bonnes pratiques du développement logiciel aux transformations SQL :

Résultat : les data analysts peuvent désormais écrire, tester et déployer leurs propres transformations sans dépendre d’un ingénieur pour chaque modification. La productivité des équipes data a été multipliée — nous l’estimons à 3x à 5x sur les projets que nous avons accompagnés.

Les forces de BigQuery : pourquoi ce duo est imbattable

Un moteur SQL serverless de classe mondiale

BigQuery est un moteur de requêtes columnar distribué qui se distingue par plusieurs caractéristiques :

Partitioning et clustering : les leviers de performance et de coût

Deux fonctionnalités de BigQuery sont fondamentales pour optimiser à la fois la performance et le coût :

Le partitioning divise physiquement une table en segments selon un champ date/timestamp ou par plage de valeurs entières. Une requête avec un filtre sur le champ de partition ne scanne que les partitions concernées — ce qui peut réduire le volume scanné de 90% sur des tables temporelles volumineuses.

Le clustering trie les données à l’intérieur de chaque partition selon 1 à 4 colonnes. Combiné au partitioning, il permet à BigQuery de prunner les blocs non pertinents avant même de les lire, pour des requêtes filtrées sur les colonnes de clustering.

-- Table BigQuery optimisée avec partitioning + clustering
CREATE TABLE `project.dataset.orders`
PARTITION BY DATE(created_at)
CLUSTER BY customer_id, status
OPTIONS (
  partition_expiration_days = 730,
  require_partition_filter = true
)
AS SELECT * FROM source_table;

Architecture en couches avec dbt : staging, intermediate, mart

L’architecture en couches est le pattern fondamental de tout projet dbt bien structuré. Elle garantit la lisibilité, la maintenabilité et la réutilisabilité des transformations.

Couche Staging (stg_)

Les modèles staging sont la porte d’entrée de vos sources brutes. Ils ont une correspondance 1:1 avec les tables sources et ne font que :

-- models/staging/stg_orders.sql
with source as (
    select * from {{ source('raw', 'orders') }}
),
renamed as (
    select
        order_id::string          as order_id,
        customer_id::string       as customer_id,
        order_date::date          as order_date,
        total_amount_cents::int   as total_amount_cents,
        lower(trim(status))       as status,
        created_at::timestamp     as created_at
    from source
    where order_id is not null
)
select * from renamed

Couche Intermediate (int_)

Les modèles intermédiaires contiennent la logique métier complexe : jointures entre staging, agrégations, calculs dérivés, pivots. Ils ne sont pas exposés aux outils BI — ils servent uniquement à construire les marts.

-- models/intermediate/int_orders_enriched.sql
with orders as (
    select * from {{ ref('stg_orders') }}
),
customers as (
    select * from {{ ref('stg_customers') }}
),
enriched as (
    select
        o.*,
        c.customer_segment,
        c.country_code,
        o.total_amount_cents / 100.0 as total_amount_eur
    from orders o
    left join customers c using (customer_id)
)
select * from enriched

Couche Mart (mart_ ou fct_ / dim_)

Les marts sont les tables finales consommées par les outils BI et les équipes métier. Ils suivent généralement le modèle dimensionnel (faits + dimensions) ou un modèle large dénormalisé selon les besoins.

Bonne pratique : dans BigQuery, configurez vos marts comme des tables matérialisées (materialized = 'table') avec partitioning et clustering selon les filtres habituels de vos dashboards. Vos requêtes BI seront 5 à 20x plus rapides et moins coûteuses.

Tests et documentation intégrés

Tests YAML : la filet de sécurité automatique

dbt propose nativement quatre tests génériques que vous pouvez appliquer à n’importe quelle colonne via un fichier YAML :

# models/staging/schema.yml
version: 2

models:
  - name: stg_orders
    description: "Commandes brutes depuis le système transactionnel"
    columns:
      - name: order_id
        description: "Identifiant unique de la commande"
        tests:
          - not_null
          - unique
      - name: status
        tests:
          - not_null
          - accepted_values:
              values: ['pending', 'confirmed', 'shipped', 'delivered', 'cancelled']
      - name: customer_id
        tests:
          - not_null
          - relationships:
              to: ref('stg_customers')
              field: customer_id

Pour des tests plus avancés, le package dbt-expectations (inspiré de Great Expectations) permet de tester des distributions, des plages de valeurs, des patterns regex, et bien plus.

Documentation automatique

Chaque description ajoutée dans les fichiers YAML est automatiquement intégrée dans le site de documentation généré par dbt docs generate && dbt docs serve. Le lineage des données est visualisable en temps réel dans le DAG interactif — précieux pour l’onboarding de nouveaux membres d’équipe et pour l’audit de gouvernance.

CI/CD avec GitHub Actions + dbt Core

Un projet dbt sans CI/CD est un projet qui finira par avoir des régressions en production. Voici une configuration GitHub Actions adaptée à BigQuery :

# .github/workflows/dbt-ci.yml
name: dbt CI

on:
  pull_request:
    paths:
      - 'models/**'
      - 'tests/**'
      - 'dbt_project.yml'

jobs:
  dbt-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dbt-bigquery
        run: pip install dbt-bigquery==1.8.*

      - name: Authenticate to GCP
        uses: google-github-actions/auth@v2
        with:
          credentials_json: ${{ secrets.GCP_SA_KEY }}

      - name: dbt deps
        run: dbt deps

      - name: dbt build (slim CI)
        run: |
          dbt build \
            --select state:modified+ \
            --defer \
            --state ./prod-artifacts \
            --target ci
        env:
          DBT_TARGET_DATASET: dbt_ci_${{ github.event.number }}

Le pattern Slim CI avec state:modified+ est clé : il ne reconstruit que les modèles modifiés et leurs dépendants, en utilisant les artefacts de production pour les modèles non modifiés. Sur un projet de 200+ modèles, cela réduit le temps de CI de 45 minutes à 3 à 5 minutes.

Optimisation des coûts BigQuery

Les modèles incrémentaux : le levier n°1

Par défaut, dbt reconstruit chaque modèle en mode table à chaque exécution — ce qui implique un scan complet de toutes les sources. Sur des tables de plusieurs milliards de lignes, c’est impraticable et coûteux. Les modèles incrémentaux ne traitent que les nouvelles données depuis la dernière exécution :

-- models/mart/fct_orders_daily.sql
{{ config(
    materialized='incremental',
    unique_key='order_date || "_" || order_id',
    partition_by={
        "field": "order_date",
        "data_type": "date",
        "granularity": "day"
    },
    cluster_by=["customer_segment", "country_code"],
    on_schema_change='append_new_columns'
) }}

select
    order_id,
    order_date,
    customer_id,
    customer_segment,
    country_code,
    total_amount_eur
from {{ ref('int_orders_enriched') }}

{% if is_incremental() %}
    -- Traite uniquement les données des 3 derniers jours
    -- (fenêtre de sécurité pour les événements tardifs)
    where order_date >= date_sub(current_date(), interval 3 day)
{% endif %}

Autres leviers d’optimisation BigQuery

Retours d’expérience concrets : 5 ans en production

Ce qui fonctionne vraiment

Après cinq ans à déployer dbt+BigQuery dans des contextes variés — retail, finance, logistique, media — voici les patterns qui s’avèrent systématiquement gagnants :

Les pièges à éviter

Chiffre clé : sur un projet e-commerce que nous accompagnons depuis 3 ans, le passage aux modèles incrémentaux avec partitioning/clustering a réduit la facture BigQuery mensuelle de 4 200€ à 380€ — sans aucune dégradation de la qualité ou de la fraîcheur des données.

Conclusion

dbt et BigQuery forment en 2026 le duo de référence pour les équipes data qui veulent allier performance, maintenabilité et maîtrise des coûts. Ce n’est pas un hasard si cette combinaison s’est imposée dans la grande majorité des projets analytics modernes que nous observons sur le marché français et européen.

La clé du succès n’est pas technique — elle est organisationnelle. dbt ne corrige pas une mauvaise architecture de données, il l’amplifie. Investissez dans la qualité de votre modélisation (staging propres, marts bien définis, tests exhaustifs) et vous disposerez d’un socle analytique qui tiendra en production pendant des années.

Si vous démarrez un nouveau projet analytics ou que vous cherchez à remettre de l’ordre dans un entrepôt de données existant, dbt+BigQuery reste notre recommandation numéro 1 pour les équipes data qui veulent se concentrer sur la valeur métier plutôt que sur la plomberie technique.

Besoin d'un expert ?

difTech vous accompagne dans vos projets data — de l'architecture à la mise en production.

📅 Réserver un créneau gratuit