Adrienne Vermorel
Premiers pas avec le dbt Semantic Layer et MetricFlow
Le dbt Semantic Layer permet de définir vos métriques une seule fois et de les interroger depuis n’importe quel outil, pour que toute l’organisation obtienne des chiffres cohérents. La mise en place est plus accessible qu’on ne le pense.
Ce guide couvre l’installation de MetricFlow, la configuration d’un premier semantic model, la définition de métriques et l’exécution de requêtes. À la fin, vous disposerez d’un semantic layer fonctionnel que vous pourrez enrichir au fil de vos besoins.
Comprendre l’architecture
MetricFlow est le moteur de génération SQL derrière le dbt Semantic Layer. Quand vous définissez des métriques en YAML, MetricFlow construit un semantic graph (une structure relationnelle qui cartographie les connexions entre vos tables via des entités). C’est un système de navigation qui sait comment joindre les tables sans que vous ayez à détailler chaque relation.
Quand vous interrogez une métrique, MetricFlow :
- Lit vos définitions YAML
- Détermine les jointures nécessaires
- Génère du SQL optimisé pour votre plateforme de données
- Exécute la requête et renvoie les résultats
MetricFlow gère la logique de jointure automatiquement. Vous définissez les entités (les clés de jointure) une seule fois, et il détermine comment naviguer entre les tables.
dbt Core vs dbt Cloud
Les fonctionnalités diffèrent entre les deux :
| Fonctionnalité | dbt Core | dbt Cloud |
|---|---|---|
| Définir semantic models et métriques | Oui | Oui |
| Générer du SQL depuis les configs | Oui | Oui |
| Requêtes via CLI | commandes mf | commandes dbt sl |
| Requêtes via APIs (JDBC, GraphQL) | Non | Oui |
| Intégrations BI | Non | Oui |
| Exports pour matérialiser les métriques | Non | Oui |
Avec dbt Core, vous bénéficiez de la définition complète des métriques et des requêtes CLI. La couche API et les intégrations BI nécessitent dbt Cloud.
Installation
Pour dbt Core, installez le bundle MetricFlow correspondant à votre adapter :
pip install "dbt-metricflow[dbt-snowflake]"Remplacez dbt-snowflake par votre adapter : dbt-bigquery, dbt-databricks, dbt-redshift ou dbt-postgres.
Pour dbt Cloud, MetricFlow est intégré. Vous utiliserez les commandes dbt sl au lieu de mf.
Plateformes supportées : Snowflake, BigQuery, Databricks, Redshift, Postgres (Core uniquement) et Trino.
Configurer le time spine
Les métriques cumulatives et les calculs temporels nécessitent un time spine, une table avec une ligne par jour. MetricFlow l’utilise comme dimension temporelle fiable pour ses jointures.
Créez un modèle appelé metricflow_time_spine.sql :
{{ config(materialized='table') }}
{{ dbt.date_spine( datepart="day", start_date="CAST('2020-01-01' AS DATE)", end_date="CAST('2030-12-31' AS DATE)") }}Puis configurez-le dans votre dbt_project.yml :
semantic-layer: time_spine: standard_granularity_column: date_dayExécutez dbt build -s metricflow_time_spine pour le matérialiser.
Définir un semantic model
Les semantic models sont des abstractions YAML qui décrivent vos modèles dbt pour MetricFlow. Chaque semantic model a une relation un-à-un avec un modèle SQL ou Python de dbt.
Ce semantic model décrit une table de commandes :
semantic_models: - name: orders description: Order transactions with revenue and quantity model: ref('mrt__sales__orders') defaults: agg_time_dimension: order__created_at
entities: - name: order_id type: primary - name: customer_id type: foreign - name: product_id type: foreign
dimensions: - name: order__created_at type: time type_params: time_granularity: day - name: order__status type: categorical - name: order__channel type: categorical
measures: - name: order_total agg: sum expr: order__amount description: Sum of order amounts - name: order_count agg: count expr: order_id description: Count of orders - name: distinct_customers agg: count_distinct expr: customer_idDétail des composants
Les entities sont les clés de jointure qui connectent les semantic models. Il en existe quatre types :
primary: un enregistrement par ligne, pas de nulls (commeorder_id)unique: un par ligne, nulls autorisésforeign: zéro à plusieurs instances (commecustomer_iddans une table de commandes)natural: colonnes identifiant de manière unique les enregistrements à partir de données réelles
Les dimensions permettent le regroupement, le découpage et le filtrage. Utilisez time pour les dates et categorical pour les valeurs textuelles.
Les measures sont les agrégations numériques qui servent de briques de base aux métriques. Agrégations supportées : sum, count, count_distinct, avg, min, max, median et percentile.
Définir des métriques
Les métriques référencent les measures que vous avez définies. Ces métriques simples s’appuient sur le semantic model des commandes :
metrics: - name: revenue description: Total order revenue type: simple label: Revenue type_params: measure: order_total
- name: orders description: Total number of orders type: simple label: Order Count type_params: measure: order_count
- name: unique_customers description: Count of distinct customers type: simple label: Unique Customers type_params: measure: distinct_customersTypes de métriques selon les besoins
Les métriques simples référencent directement une measure, comme les exemples ci-dessus.
Les métriques dérivées se calculent à partir d’autres métriques. Cet exemple calcule le revenu par client :
metrics: - name: revenue_per_customer description: Average revenue per unique customer type: derived label: Revenue per Customer type_params: expr: revenue / unique_customers metrics: - name: revenue - name: unique_customersLes métriques ratio calculent correctement les ratios en agrégeant numérateur et dénominateur indépendamment avant la division :
metrics: - name: average_order_value description: Average value per order type: ratio label: AOV type_params: numerator: order_total denominator: order_countLes métriques cumulatives agrègent sur des fenêtres temporelles :
metrics: - name: revenue_mtd description: Month-to-date revenue type: cumulative label: Revenue MTD type_params: measure: order_total grain_to_date: monthValider votre configuration
Avant d’interroger vos métriques, validez que vos définitions sont correctement parsées :
# dbt Coremf validate-configs
# dbt Clouddbt sl validateEn cas d’échec de la validation, vérifiez ces problèmes courants :
- Erreur “ensure that you’ve ran an artifacts…” : exécutez
dbt parseoudbt buildd’abord pour générer le semantic manifest. - Conflit Metafont : la commande
mfpeut entrer en conflit avec le package LaTeX Metafont. Désinstallez-le si vous observez un comportement inattendu. - Dimensions absentes : chaque dimension a besoin d’une entité primaire dans son semantic model.
Interroger les métriques
Générez d’abord le semantic manifest :
dbt parsePuis interrogez vos métriques :
# dbt Coremf query --metrics revenue --group-by metric_time
# dbt Clouddbt sl query --metrics revenue --group-by metric_timeAjoutez des dimensions pour découper les résultats :
mf query --metrics revenue,orders --group-by metric_time,order__channelFiltrez avec le flag --where :
mf query --metrics revenue --group-by metric_time --where "{{ Dimension('orders__order__channel') }} = 'web'"La syntaxe de filtre utilise du templating Jinja. Référencez les dimensions avec {{ Dimension('semantic_model__dimension_name') }}.
Organiser les semantic models à grande échelle
Pour les petits projets, regroupez les définitions sémantiques avec vos modèles dbt :
models/ marts/ mrt__sales__orders.sql mrt__sales__orders.yml # semantic model + métriques mrt__sales__customers.sql mrt__sales__customers.ymlPour les projets plus importants, séparez-les dans des répertoires dédiés :
models/ marts/ mrt__sales__orders.sql mrt__sales__customers.sql semantic/ semantic_models/ sem_orders.yml sem_customers.yml metrics/ revenue_metrics.yml customer_metrics.ymlUn exemple complet
Voici l’ensemble en pratique avec un modèle de commandes :
-- models/marts/mrt__sales__orders.sqlSELECT order_id, customer_id, created_at AS order__created_at, channel AS order__channel, status AS order__status, amount AS order__amountFROM {{ ref('int__orders_enriched') }}Définition du semantic layer :
semantic_models: - name: orders model: ref('mrt__sales__orders') defaults: agg_time_dimension: order__created_at
entities: - name: order_id type: primary - name: customer_id type: foreign
dimensions: - name: order__created_at type: time type_params: time_granularity: day - name: order__status type: categorical - name: order__channel type: categorical
measures: - name: order_total agg: sum expr: order__amount - name: order_count agg: count expr: order_id
metrics: - name: revenue type: simple type_params: measure: order_total
- name: orders type: simple type_params: measure: order_count
- name: aov type: ratio type_params: numerator: order_total denominator: order_countBuild et requête :
dbt builddbt parsemf query --metrics revenue,aov --group-by metric_time,order__channelEt ensuite
Une fois votre semantic layer opérationnel, vous pouvez :
- Ajouter d’autres semantic models pour les clients, produits et autres entités. MetricFlow gère automatiquement les jointures via les entités partagées.
- Définir des métriques period-over-period avec des métriques dérivées et
offset_windowpour des comparaisons comme la croissance mois par mois. - Connecter des outils BI (dbt Cloud) via JDBC ou l’API GraphQL.
- Exposer vos métriques aux LLMs en donnant accès à vos métriques gouvernées aux outils d’IA capables d’interroger en langage naturel des définitions cohérentes.
La vraie valeur apparaît quand plusieurs équipes interrogent les mêmes métriques et obtiennent les mêmes résultats, sans maintenir de logique dupliquée dans les dashboards et les rapports.