La dette technique SQL, on la connaît tous :
- des vues imbriquées sur 7 niveaux
- des procédures stockées écrites à 4 mains, non versionnées
- des logiques métiers encapsulées dans des sous-requêtes sans nom
- aucun test, aucune documentation, aucune visibilité
🎯 L’objectif ? Basculer progressivement ce spaghetti SQL dans une architecture claire, modulaire et gouvernée avec un outil moderne, comme par exemple dbt.
🧭 Étape 1 – Comprendre le legacy
Avant de toucher à une ligne de code :
- on importe sous dbt notre amas SQL dans un dossier « models » afin de pouvoir s’y référer
- on identifie les sources afin de les déclarer comme tel et rendre le lineage plus lisible
- on mappe les dépendances entre objets (vue A appelle B qui appelle C… le brouillon du futur DAG)
- on identifie les tables finales réellement utilisées par les consommateurs
- on repère les tables pivot (clients, contrats, transactions…)
📌 Astuce : un petit EXPLAIN bien placé permet d’identifier rapidement la hiérarchie d’appels
🧪 Étape 2 – Choix de la stratégie de refactoring
2 stratégies sont possibles:
- in-place refactoring: travailler directement sur le sql legacy que nous avons importé
- alongside refactoring: travailler sur un répertoire dédié le nouveau modèle
dbt préconise de façon assez évidente la seconde stratégie: moins d’impacte sur l’utilisateur final, plus simple à auditer, lisibilité dans git etc…
On découpe alors notre nouveau modèle comme suit :
stg_pour les données brutes nettoyéesint_pour la logique métier (calculs, règles, mappings)mart_pour les données prêtes à être consommées (dashboards, reporting)
➡️ Exemple :
-- stg_transaction.sql
select id, date_tx, montant_txfrom source_legacy.transactions
-- int_client_revenus.sql
select id_client, sum(montant_tx) as revenu_12mfrom {{ ref('stg_transaction') }}
group by id_client
-- mart_clients_segments.sql
select c.id_client, c.segment, r.revenu_12m
from {{ ref('stg_clients') }} c
left join {{ ref('int_client_revenus') }} r using(id_client)
💡 Si une logique métier est trop obscure, on la factorise en macro ou on y met des commentaires clairs. L’objectif est de rendre le code le plus modulaire possible.
🧼 Étape 3 – Structurer le contenu de nos modèles
Une fois les modèles définis, il s’agit de structurer leur contenu. dbt propose le pattern suivant:
Ré-écrire sous forme de CTEs les requêtes:
- les CTE ‘Import’ -> on importe les modèles déjà existants
- les CTE ‘Logique’ -> on intègre une logique métier, des champs calculés, etc..
- une CTE ‘Finale’ -> la vue finale
- On termine l’écriture du modèle par un simple select * de notre CTE finale
📚 Étape 4 – Tester et Documenter
Une fois la chaîne reconstituée :
- on gère les tests automatiquement via les generic tests (
not null,unique,relationship) - on utilise
exposurespour lier les dashboards Tableau/Power BI aux modèles - on publie une documentation automatique avec
dbt docs generate - on ajoute des tags pour filtrer les modèles par usage :
#marketing,#finance,#audit, etc.
🧘 Étape 5 – Migration progressive
Plutôt que de tout basculer d’un coup :
- On recrée les flux critiques dans
dbt - On compare les résultats avec les tables legacy (
minus,except) - On décommissionne par lots si besoin
📎 Le guide officiel de dbt ➡️
https://docs.getdbt.com/guides/refactoring-legacy-sql?step=1
💡 Migrer un legacy SQL vers dbt, c’est transformer un enchevêtrement de vues SQL en une architecture modulaire, testée et gouvernée.
Le fond reste le même, mais tout devient plus clair, plus fiable, plus scalable.
#dbt #SQL #AnalyticsEngineering #DataRefactoring #ModernDataStack #DataModelling #BusinessDataAnalyst #DataQuality #GouvernanceDesDonnées #DataOps
