07 — Documentation et gouvernance
La documentation est le seul travail data que tout le monde reporte et que l'IA fait vraiment bien. Profites-en : c'est ton gain le plus rapide.
Temps de lecture : 18 min | Niveau : Avancé
Ce que tu sauras faire après
- Faire documenter tables et colonnes sans obtenir des paraphrases inutiles.
- Produire un dictionnaire de données complet et maintenable.
- Écrire une définition de métrique certifiée, non ambiguë.
- Maintenir un glossaire métier partagé entre la technique et le business.
- Comprendre pourquoi la couche sémantique et MCP rendent l'IA fiable sur tes chiffres.
1. Pourquoi c'est le meilleur usage de l'IA en data
Trois raisons :
- Le matériau est déjà là. Le SQL du modèle contient la logique. Le DDL contient les types. Il suffit de les coller.
- Le coût d'une erreur est faible. Une description imparfaite se corrige en dix secondes. Une requête fausse coûte une réunion.
- Personne ne le fait. Donc l'écart entre « pas de doc » et « doc correcte » est énorme, et immédiat.
Mais attention à un piège très courant : le modèle produit facilement des descriptions qui paraphrasent le nom de la colonne.
| Mauvaise description | Pourquoi c'est nul |
|---|---|
client_id : « l'identifiant du client » | N'apporte rien. Le nom le disait déjà. |
montant_ttc : « le montant TTC » | Ne dit pas la devise, ni si les remises sont incluses. |
date_commande : « la date de la commande » | Ne dit pas le fuseau, ni si c'est la prise ou la validation. |
Une bonne description répond à ce que le nom ne dit pas : unité, fuseau horaire, ce qui est inclus ou exclu, valeurs possibles, cas particuliers.
| Bonne description |
|---|
montant_ttc : « Montant total de la commande, en euros, TVA incluse. Remises déduites. Les frais de port ne sont pas inclus. Négatif possible sur un avoir. » |
date_commande : « Date de prise de commande par le client, fuseau Europe/Paris. Différente de la date de validation du paiement, qui peut être le lendemain. » |
2. Documenter dans dbt
C'est le point d'entrée naturel : ce que tu écris dans dbt peut ensuite être poussé partout.
Les descriptions
models:
- name: events
description: This table contains clickstream events from the marketing website
columns:
- name: event_id
description: This is a unique identifier for the eventLes blocs docs, pour les textes longs
Quand une description dépasse deux lignes, ou quand elle est réutilisée à plusieurs endroits, dbt propose les blocs docs : un fichier .md contenant la balise Jinja docs.
{% docs table_events %}
Événements de navigation du site marketing.
Granularité : une ligne par événement.
Source : collecteur front, chargé toutes les heures.
Attention : les sessions robots ne sont PAS filtrées à ce niveau.
{% enddocs %}Référencé avec la fonction doc() :
description: '{{ doc("table_events") }}'La doc mentionne aussi la possibilité d'extensions Jinja (.md.j2, .md.jinja, .md.jinja2) lorsque allow_jinja_file_extensions: true est défini dans dbt_project.yml.
Générer et consulter le site
dbt docs generate # compile le projet et écrit le site statique
dbt docs serve # ouvre le site en localPoint de version. La page consultée indique que
dbt docs generate« is available for dbt v2.0 and later » et produit des artefacts Parquet v2. Si tu es sur une version antérieure, contrôle le comportement dans la doc de ta version.
Pousser la doc dans l'entrepôt
persist_docs recopie tes descriptions dbt en commentaires de relation et de colonne dans la base elle-même :
models:
mon_projet:
+persist_docs:
relation: true
columns: trueAdaptateurs supportant les deux niveaux d'après la doc : Postgres, Redshift, Snowflake, BigQuery, Databricks, Apache Spark, Starburst Galaxy (dbt-trino). À savoir : sur Databricks les commentaires de colonne exigent file_format: delta, et les sources ne supportent pas persist_docs.
C'est le geste qui change tout : la personne qui ouvre la table dans la console de l'entrepôt, sans connaître dbt, voit quand même la description.
Côté BigQuery, directement
Si tu n'es pas sur dbt, tu peux poser la description en SQL :
ALTER TABLE mydataset.mytable
SET OPTIONS (
description = 'Description of mytable');Ou en ligne de commande :
bq update --description "Description of mytable" mydataset.mytableAu niveau colonne, la voie documentée est de poser la description dans le schéma, au moment où tu définis la table. En DDL, ça donne ceci :
CREATE TABLE mydataset.newtable (
x INT64 OPTIONS(description="This column stores integer values"),
y STRING
)
OPTIONS(description='My example table');Et en définition de schéma JSON :
[
{
"name": "qtr",
"type": "STRING",
"mode": "REQUIRED",
"description": "quarter"
}
]La doc précise la limite : « Each column can include an optional description. The description is a string with a maximum length of 1,024 characters. » Mille caractères, c'est large : tu as la place de dire l'unité, le fuseau et les exclusions.
Ce que je n'ai pas pu vérifier. La syntaxe
ALTER TABLE ... ALTER COLUMN ... SET OPTIONS(description = ...), pour modifier une description de colonne après coup, ne figurait pas dans les pages officielles que j'ai réussi à ouvrir. Si tu en as besoin, vérifie-la dans la référence DDL GoogleSQL avant d'industrialiser. Et de toute façon, le chemin le plus maintenable restepersist_docsdepuis dbt : ta description vit dans Git, pas dans unALTERlancé à la main.
3. Le dictionnaire de données
Un dictionnaire de données, c'est une table qui décrit tes tables. Les colonnes minimales, dans l'ordre :
| Colonne | Contenu |
|---|---|
table | Nom complet, avec projet et jeu de données |
colonne | Nom de la colonne |
type | Type technique |
description | Ce que le nom ne dit pas |
unite | Euros, jours, pourcentage, nombre |
valeurs_possibles | Pour les énumérations |
obligatoire | Peut-elle être nulle |
cle | Primaire, étrangère, ou rien |
proprietaire | Équipe ou personne responsable |
sensibilite | Public, interne, personnel |
Le squelette se génère depuis les métadonnées de l'entrepôt. Sur BigQuery, c'est la vue INFORMATION_SCHEMA.COLUMNS qui fournit les métadonnées de colonnes.
Les colonnes de cette vue que tu utiliseras en pratique : table_catalog, table_schema, table_name, column_name, data_type, is_nullable, description.
-- Squelette du dictionnaire, colonnes nommées explicitement
SELECT
table_catalog,
table_schema,
table_name,
column_name,
data_type,
is_nullable,
description
FROM `mon_projet.mon_dataset.INFORMATION_SCHEMA.COLUMNS`
WHERE table_name = 'fct_commandes'
ORDER BY table_name, column_name;Deux précautions :
- Nomme tes colonnes, n'écris pas
SELECT *. Google recommande de lister explicitement les colonnes dans les requêtesINFORMATION_SCHEMA: si le schéma de la vue évolue, ta requête ne casse pas. - Lance quand même un
SELECT *une fois, en exploration, pour voir ce que ta version expose réellement chez toi. Puis fige la liste. Ne te fie jamais à une liste de colonnes qu'un modèle te sortirait de mémoire.
Pour les champs imbriqués et répétés (RECORD, REPEATED), la vue INFORMATION_SCHEMA.COLUMN_FIELD_PATHS donne le chemin complet de chaque sous-champ. C'est elle qu'il te faut si ton entrepôt contient du JSON aplati.
Méthode qui marche : tu exportes le squelette en CSV, tu le colles dans le prompt, et tu demandes uniquement de remplir la colonne description. Le reste vient de la base, pas du modèle. C'est ce découpage qui empêche l'invention.
4. Les métriques certifiées
C'est le cœur de la gouvernance. Une métrique certifiée, c'est un indicateur dont la définition est écrite, unique, et fait autorité.
Sans ça, trois personnes calculent « le chiffre d'affaires » de trois façons différentes, et la réunion porte sur les écarts au lieu de porter sur le métier.
Ce que contient une définition certifiée
- Nom exact, et nom d'affichage pour les outils.
- Définition en une phrase, en français, compréhensible par le métier.
- Formule, en SQL ou en pseudo-code.
- Périmètre inclus : quelles lignes entrent dans le calcul.
- Périmètre exclu : ce qui est explicitement sorti. Le bloc le plus important.
- Granularité et dimensions d'analyse autorisées.
- Période de référence : mois calendaire, exercice fiscal, semaine du lundi au dimanche.
- Propriétaire et date de dernière révision.
Le bloc 5 est celui qui résout les litiges. « Le CA exclut les avoirs, les commandes annulées et les commandes de test » : trois lignes qui évitent trois réunions.
MetricFlow : coder la définition
dbt permet de déclarer ces métriques dans des fichiers YAML. Les clés documentées :
| Clé | Rôle | Obligatoire |
|---|---|---|
name | Nom de référence, en minuscules, chiffres et tirets bas | oui |
type | simple, cumulative, derived, ratio ou conversion | oui |
description | La définition en clair | non |
label | Libellé affiché dans les outils en aval | non |
filter | Clause de filtrage sur dimensions, entités ou métriques | non |
config | meta, group, tags, enabled | non |
Les cinq types, avec les clés propres à chacun. Ce tableau t'évite de deviner :
| Type | Ce qu'il calcule | Clés propres au type |
|---|---|---|
simple | Une agrégation sur un champ | agg, expr |
cumulative | Une métrique cumulée sur une fenêtre de temps | window, input_metric |
derived | Un calcul à partir d'autres métriques | expr, input_metrics |
ratio | Un numérateur divisé par un dénominateur | numerator, denominator |
conversion | Un événement de base suivi d'un événement de conversion | entity, calculation, base_metric, conversion_metric |
Attention au singulier et au pluriel : input_metric pour une cumulative, input_metrics pour une derived. C'est une faute de frappe classique, et le message d'erreur n'est pas toujours parlant.
Deux emplacements de déclaration, avec une contrainte à connaître : les métriques simples se déclarent dans le modèle sémantique, pas au niveau supérieur. La doc est explicite : « Simple metrics can't be defined at the top level. »
# Métrique simple : DANS le modèle sémantique
models:
- name: fct_commandes
semantic_model:
enabled: true
# colonnes, dimensions, entités...
metrics:
- name: ca_ttc
description: Chiffre d'affaires TTC, hors commandes annulées.
type: simple
label: CA TTC
agg: sum
expr: montant_ttc
fill_nulls_with: 0# Métrique avancée : AU NIVEAU SUPÉRIEUR
metrics:
- name: ca_ttc_cumule_semaine
type: cumulative
label: CA TTC cumulé sur 7 jours
input_metric:
name: ca_ttc
window: 1 weekPrécision d'honnêteté. La page officielle consultée ne présente ni
type_paramsnimeasurecomme clés standard. Les paramètres dépendent du type de métrique, comme dans le tableau ci-dessus. Beaucoup d'articles de blog et beaucoup de modèles de langage te proposeronttype_params: avant de l'écrire, vérifie dans la doc de ta version de dbt. C'est exactement le genre de détail où l'IA recycle une syntaxe périmée avec un aplomb parfait.
5. Le glossaire métier
Le dictionnaire de données décrit des colonnes. Le glossaire métier décrit des mots.
Trois entrées typiques :
- Client actif : « client ayant passé au moins une commande validée dans les 12 derniers mois glissants. » Et non pas « client ayant un compte ».
- Exercice : « période du 1er juillet au 30 juin. L'exercice 2026-2027 court du 1er juillet 2026 au 30 juin 2027. » Et non pas l'année civile.
- Périmètre constant : « uniquement les entités ouvertes sur toute la période comparée, des deux côtés. »
Chaque entrée porte : le terme, la définition, un exemple, un contre-exemple, le propriétaire, la date de révision. Le contre-exemple fait la moitié du travail : il dit ce que le terme n'est pas.
L'IA maintient bien un glossaire à condition que tu lui donnes les entrées existantes à chaque fois. Sinon elle réinvente un style différent à chaque ajout, et le glossaire devient incohérent.
6. Le lien avec la couche sémantique et MCP
Voici le raisonnement qui relie cette fiche à toute la section.
Quand tu colles un schéma dans un prompt, le modèle travaille sur une photo de ton modèle de données. Cette photo vieillit, et elle ne contient pas tes définitions certifiées.
Une couche sémantique (les métriques MetricFlow, par exemple) fait autre chose : elle expose des indicateurs déjà définis, avec leurs règles, au lieu d'exposer des tables brutes. L'outil qui l'interroge ne recalcule pas le CA : il demande le CA.
MCP (Model Context Protocol) est le standard ouvert qui permet de brancher un assistant sur ce genre de service. La documentation Claude Code le décrit ainsi :
« Claude Code can connect to hundreds of external tools and data sources through the Model Context Protocol (MCP), an open source standard for AI-tool integrations. MCP servers give Claude Code access to your tools, databases, and APIs. »
Ajouter un serveur MCP, selon la doc officielle :
# Serveur distant en HTTP (recommandé)
claude mcp add --transport http <name> <url>
# Serveur local en stdio
claude mcp add [options] <name> -- <command> [args...]
# Lister, inspecter, retirer
claude mcp list
claude mcp get <name>
claude mcp remove <name>Les transports documentés : HTTP (recommandé pour le distant), SSE (déprécié, remplacé par HTTP), stdio (processus local), WebSocket. Les portées d'installation : local (projet courant, non partagé), project (partagé via .mcp.json dans le dépôt), user (tous tes projets).
Ce que ça change concrètement pour toi. Sans MCP, l'assistant devine ta définition du CA. Avec un serveur MCP branché sur ta couche sémantique, il appelle l'indicateur certifié et rend le chiffre officiel, avec ses règles appliquées. Le travail de documentation décrit dans cette fiche est exactement ce qui rend ce branchement fiable. Un serveur MCP posé sur des métriques mal définies ne fait qu'une chose : diffuser l'ambiguïté plus vite.
Les détails d'installation et de sécurité sont traités dans la section 09-mcp.
🧰 Templates à copier-coller
Template A — Documenter un modèle et ses colonnes
<sql_du_modele>
[COLLE_LE_SQL]
</sql_du_modele>
<contexte>
Rôle métier de la table : [A_QUOI_ELLE_SERT]
Granularité : une ligne par [GRANULARITE]
Fréquence de rafraîchissement : [FREQUENCE]
Propriétaire : [EQUIPE_OU_PERSONNE]
</contexte>
Écris le fichier .yml de documentation.
Règle absolue sur les descriptions de colonnes : INTERDICTION de paraphraser
le nom de la colonne. Chaque description doit apporter au moins une de ces
informations :
- l'unité ou la devise ;
- le fuseau horaire, pour une date ou un horodatage ;
- ce qui est inclus ET ce qui est exclu ;
- les valeurs possibles, pour une énumération ;
- un cas particulier ou un piège connu.
Exemple de description INTERDITE : "client_id : l'identifiant du client".
Pour toute colonne dont tu ne peux pas déduire ces informations du SQL,
écris exactement : "description: TODO — [la question précise à poser au métier]".
N'invente aucun sens métier.Template B — Remplir un dictionnaire de données
Voici le squelette de dictionnaire exporté depuis les métadonnées de
l'entrepôt. Les colonnes table, colonne, type, obligatoire viennent de la
base : ne les modifie JAMAIS.
<squelette>
[COLLE_LE_CSV_EXPORTE]
</squelette>
<contexte_metier>
[DECRIS_LE_DOMAINE_ET_LES_REGLES_CONNUES]
</contexte_metier>
Remplis uniquement les colonnes : description, unite, valeurs_possibles,
cle, sensibilite.
Contraintes :
- description : ce que le nom ne dit pas (unité, fuseau, inclusions,
exclusions, pièges). Jamais une paraphrase du nom.
- sensibilite : public | interne | personnel. En cas de doute, mets
"personnel" et signale-le.
- Quand tu ne peux pas déduire une valeur, écris "TODO — [question à poser]"
plutôt que de deviner.
Rends le CSV complété, puis séparément la liste de tous les TODO regroupés,
pour que je puisse les poser en une seule fois au métier.Template C — Rédiger une définition de métrique certifiée
Rédige la fiche de définition certifiée de l'indicateur "[NOM_INDICATEUR]".
<elements_connus>
Formule actuelle (SQL ou description) :
[COLLE]
Ce qui est inclus : [LISTE]
Ce qui est exclu : [LISTE]
Période de référence : [MOIS_CALENDAIRE | EXERCICE_FISCAL_DU_X_AU_Y | SEMAINE_LUNDI_DIMANCHE]
Granularités d'analyse autorisées : [LISTE]
Propriétaire : [QUI]
</elements_connus>
Produis une fiche en 8 blocs :
1. Nom technique et nom d'affichage.
2. Définition en UNE phrase, compréhensible par un non-technicien.
3. Formule.
4. Périmètre inclus.
5. Périmètre exclu — le bloc le plus détaillé.
6. Granularité et dimensions d'analyse autorisées.
7. Période de référence et règle de comparaison N-1.
8. Propriétaire et date de révision.
Termine par <ambiguites_restantes> : toute zone que les éléments fournis ne
tranchent pas, formulée en question fermée à poser au métier.
N'invente aucune règle d'inclusion ou d'exclusion.Template D — Maintenir un glossaire métier
<glossaire_existant>
[COLLE_LES_ENTREES_DEJA_ECRITES_POUR_QUE_LE_STYLE_RESTE_COHERENT]
</glossaire_existant>
<nouveaux_termes>
[LISTE_DES_TERMES_A_AJOUTER]
</nouveaux_termes>
<informations_disponibles>
[TOUT_CE_QUE_TU_SAIS_SUR_CES_TERMES_MEME_PARTIEL]
</informations_disponibles>
Pour chaque nouveau terme, rédige une entrée dans EXACTEMENT le même format
que les entrées existantes, avec :
- le terme ;
- la définition en une phrase ;
- un exemple concret ;
- un CONTRE-exemple (ce que le terme n'est pas) ;
- les termes voisins à ne pas confondre ;
- le propriétaire et la date.
Le contre-exemple est obligatoire : c'est lui qui évite les confusions.
Si les informations fournies ne suffisent pas pour un terme, écris l'entrée
avec "définition : À VALIDER" et la question précise à poser.A retenir
- Une description utile dit ce que le nom ne dit pas : unité, fuseau, inclusions, exclusions, pièges.
persist_docspousse tes descriptions dbt jusque dans les commentaires de l'entrepôt : c'est le geste qui rend la doc visible hors de dbt.- Pour un dictionnaire de données : la structure vient de
INFORMATION_SCHEMA, seule la description vient du modèle. Ce découpage empêche l'invention. - Une métrique certifiée se juge à son bloc « périmètre exclu ».
- Dans MetricFlow : cinq types (
simple,cumulative,derived,ratio,conversion), chacun avec ses propres clés, et les métriques simples ne se déclarent pas au niveau supérieur. - En BigQuery, la description de colonne se pose dans le schéma, avec
OPTIONS(description="...")en DDL ou le champdescriptionen JSON. Limite : 1 024 caractères. - Une couche sémantique exposée via MCP fait appeler l'indicateur officiel au lieu de le faire recalculer : mais elle ne vaut que ce que vaut ta documentation.
Sources
- About documentation — dbt Developer Hub
- persist_docs — dbt Developer Hub
- Metrics overview — dbt Developer Hub
- Managing tables — BigQuery, Google Cloud
- Specify a schema — BigQuery, Google Cloud
- INFORMATION_SCHEMA COLUMNS view — BigQuery, Google Cloud
- INFORMATION_SCHEMA COLUMN_FIELD_PATHS view — BigQuery, Google Cloud
- Data definition language (DDL) statements — BigQuery, Google Cloud
- Connect Claude Code to tools via MCP — Claude Code Docs
- Claude Code overview — Claude Code Docs