C'est l'une des questions les plus fréquentes que je vois sur les forums de la communauté Fabric :
« Est-ce que je dois construire cette transformation dans un Dataflow Gen2 ou dans un Fabric Notebook ? »
La documentation officielle dit : « Utilisez les Dataflows pour les transformations low-code, utilisez les Notebooks pour la logique complexe. » Ce n'est pas un framework de décision. C'est un slogan.
En pratique, le mauvais choix vous coûte des CUs, du temps de debug et de la maintenabilité. Voici un framework qui répond vraiment à la question, construit à partir de l'expérience sur de vrais workloads.
01.Les 5 dimensions qui comptent vraiment
Avant l'arbre de décision : voici les facteurs qui changent réellement la réponse.
| Dimension | Pourquoi ça change tout |
|---|---|
| Volume de lignes | Dataflow utilise le moteur Mashup (mono-noeud) ; le Notebook utilise Spark (distribué) |
| Complexité des transformations | M / Power Query vs PySpark/SQL, plafond très différent |
| Orchestration | Les deux s'intègrent aux pipelines, mais différemment |
| Coût CU | Dataflow facture par query à 12 CU/s ; Spark facture par session (4–8 CU/s selon le pool) |
| Compétences de l'équipe | Power Query est accessible aux analystes ; PySpark demande du niveau ingénieur |
| Réutilisabilité | Les Notebooks s'importent comme modules ; les Dataflows non |
02.L'arbre de décision
Chargement vers Lakehouse avec transformations légères ET moins de 5M de lignes
Filtres, renommages, cast uniquement. Le moteur Mashup gère ça de manière efficace.
Chargement vers Lakehouse ET plus de 5M de lignes OU jointures sur grandes tables
Spark passe à l'échelle horizontalement. Le moteur Mashup, non.
Logique métier complexe : pivots, agrégations personnalisées, features ML, fonctions fenêtre.
L'audience est des analystes / équipe BI (pas de Python)
Power Query est leur langage. N'imposez pas PySpark.
Besoin de tests unitaires, logique versionnée, fonctions réutilisables
Les Notebooks supportent pytest, les fichiers .py gérés par Git, les modules importables.
Chargement de la même source vers 10+ tables de sortie
Utilisez le query referencing : 1 évaluation source × N tables de sortie = bien moins cher : Dataflow lit la source une seule fois, un job Spark la lirait N fois.
Rafraîchissement incrémental / pattern watermark ET moins d'1M de lignes/jour
Le watermark avec List.Max est rapide et économique pour les petites charges quotidiennes.
Rafraîchissement incrémental avec merge complexe / upsert / SCD2MERGE INTO en Spark SQL gère la gestion de l'historique. Power Query ne peut pas.
03.La réalité des coûts CU
C'est là que la décision devient contre-intuitive. Voici les chiffres réels.
Facturation Dataflow Gen2
Dataflow Gen2 facture par query de sortie, à :
- 12 CU/seconde pour les 10 premières minutes de chaque query
- 1,5 CU/seconde au-delà de 10 minutes (8× moins cher)
Plus en option : High Scale Compute (Staging) : 6 CU/s fixe quand activé | Fast Copy : 1,5 CU/s quand applicable.
MÊMES 10 TABLES AVEC QUERY REFERENCING 1 query source (partagée) + 10 petites queries de filtre ≈ ~80% de réduction
Facturation Spark (Notebook / Spark Job Definition)
Les jobs Spark (exécutés via Notebook ou Spark Job Definition) facturent par session Spark (pas par query) :
- Starter pool : démarre à 4 CU/s (8 vCores), monte à 8 CU/s minimum après scale-up automatique ; Custom Pool Small : 2 CU/s
- La session est partagée entre toutes les cellules
Comparaison directe
| Scénario | Dataflow Gen2 | Spark (Notebook) |
|---|---|---|
| 5 petites tables, 30s chacune | ~900 CU | ~1 200 CU |
| 20 tables depuis la même source | ~14 400 CU (sans ref) → ~3 000 CU (avec ref) | ~4 800 CU |
| 1 table, 50M lignes, jointure lourde | Très lent / OOM | ~6 000 CU (Spark s'adapte) |
| Rafraîchissement incrémental, 100k lignes/jour | ~720 CU | ~2 400 CU |
Pour de nombreuses petites tables depuis la même source, Dataflow Gen2 avec query referencing gagne. Pour les grands volumes ou la logique complexe, le Notebook gagne.
04.4 scénarios concrets
Scénario A : Charger un fichier Excel SharePoint dans 15 tables Lakehouse
Créez une query de base qui lit le fichier Excel. Référencez-la 15 fois avec des queries Reference, une par onglet/table de sortie. SharePoint est lu une seule fois ; les 15 tables sont dérivées en mémoire.
Si vous utilisez un Notebook ici, vous ouvrez le fichier Excel 15 fois (15 appels HTTP vers SharePoint), vous le parsez 15 fois, et vous payez 15 lectures Spark séparées d'un format non-natif.
Scénario B : Construire une table de faits Gold avec SCD Type 2
Ce n'est pas exprimable en Power Query. N'essayez pas.
spark.sql("""
MERGE INTO gold.dim_customer AS target
USING (SELECT * FROM silver.stg_customer) AS source
ON target.customer_id = source.customer_id AND target.is_current = true
WHEN MATCHED AND (target.email != source.email OR target.city != source.city) THEN
UPDATE SET target.is_current = false, target.end_date = current_date()
WHEN NOT MATCHED THEN
INSERT (customer_id, email, city, start_date, end_date, is_current)
VALUES (source.customer_id, source.email, source.city, current_date(), null, true)
""")
Scénario C : Chargement incrémental quotidien, 200k lignes depuis SQL Server
Un job Spark coûterait 10–15× plus cher par exécution pour la même logique : la session Spark (4–8 CU/s) tourne pendant toute sa durée, même pour une petite charge incrémentale.
// Query helper watermark
LastLoadDate = List.Max(
Table.Column(Lakehouse.Contents(...){[Name="fact_sales"]}[Data], "load_date"),
#date(2020, 1, 1)
)
// Query principale : filtrer la source avant chargement
FilteredRows = Table.SelectRows(Source, each [created_at] > LastLoadDate)
Scénario D : Table de faits de 200M lignes, fonctions fenêtre complexes
Le moteur Mashup de Dataflow Gen2 tourne sur un seul noeud. À 200M lignes avec des fonctions fenêtre, vous atteindrez les limites mémoire ou des temps d'exécution extrêmes. Spark distribue le travail, c'est précisément pour ça qu'il est fait.
from pyspark.sql.window import Window
from pyspark.sql.functions import lag, col
w = Window.partitionBy("customer_id").orderBy("order_date")
df = df.withColumn("prev_order_date", lag("order_date", 1).over(w)) \
.withColumn("days_since_last_order",
(col("order_date").cast("long") - col("prev_order_date").cast("long")) / 86400)
05.Quand utiliser les deux ensemble
Le pattern le plus puissant est un pipeline qui combine les deux outils :
[Dataflow Gen2] [Notebook]
Charger les données brutes → Appliquer la logique métier
(Excel, SharePoint, APIs) (SCD2, agrégations, features ML)
Écrire en Bronze/Silver → Écrire en Gold Lakehouse
Dataflow gère l'extraction et la normalisation légère (son point fort). Le Notebook gère la logique de transformation (son point fort). Aucun outil n'est forcé à faire ce pour quoi il est mauvais.
06.Carte de référence rapide
| Si vous avez besoin de... | Utilisez |
|---|---|
| Low-code, accessible aux analystes | Dataflow Gen2 |
| Plusieurs tables depuis la même source | Dataflow Gen2 + query referencing |
| Plus de 10M lignes avec transformations lourdes | Notebook |
| SCD2 / MERGE INTO / upserts | Notebook |
| Tests unitaires pour votre logique | Notebook |
| Rafraîchissement incrémental < 1M lignes/jour | Dataflow Gen2 |
| Fonctions fenêtre complexes | Notebook |
| Fonctions Python réutilisables en bibliothèque | Notebook |
| L'équipe non-technique maintient le code | Dataflow Gen2 |