Accueil A propos Tech Stack Projets Blog Tracker
Retour au Blog

Microsoft Fabric Lakehouse :
10 Best Practices pour le Data Engineering

Guide complet pour optimiser vos Delta Tables dans Microsoft Fabric : V-Order, OPTIMIZE, VACUUM, Z-ORDER, et patterns d'ingestion avec des exemples PySpark concrets.

Sommaire
  1. Delta Lake : le format standard du Lakehouse
  2. Activer V-Order selon votre workload
  3. Tirer parti d'Optimize Write
  4. Lancer OPTIMIZE pour la bin-compaction
  5. Nettoyer avec VACUUM
  6. Utiliser Z-ORDER sur les colonnes filtrees
  7. Adopter l'architecture Medallion
  8. Choisir les bons modes d'ecriture
  9. Exploiter Low Shuffle Merge
  10. Automatiser la maintenance

Dans Microsoft Fabric, le Lakehouse est le coeur de l'architecture Data. Toutes les donnees sont stockees au format Delta Lake dans OneLake, ce qui offre une base unifiee pour tous les moteurs analytiques (Spark, SQL, Power BI). Mais pour tirer le meilleur parti de cette architecture, il faut connaitre les bonnes pratiques d'optimisation.

Voici 10 best practices essentielles que j'applique au quotidien sur mes projets Fabric, avec des exemples de code PySpark directement utilisables dans vos notebooks.

01. Delta Lake : le format standard du Lakehouse

Dans Fabric, Delta Lake est le format par defaut pour toutes les tables. Contrairement a Azure Synapse où le format par defaut etait Parquet, Fabric utilise Delta nativement. Cela signifie que vous beneficiez automatiquement du support ACID, du time travel, et du schema enforcement.

Point cle

Toutes les tables visibles dans l'explorateur Lakehouse sont des tables Delta optimisees. Quand vous chargez des donnees (CSV, Parquet, JSON), Fabric les convertit automatiquement en Delta.

Config Spark Fabric Azure Synapse
spark.sql.sources.default delta parquet
spark.sql.parquet.vorder.default false (configurable) N/A
optimizeWrite.enabled true false

02. Activer V-Order selon votre workload

V-Order est une optimisation d'ecriture sur le format Parquet, specifique a Fabric. Elle reorganise les donnees au moment de l'ecriture pour accelerer considerablement les lectures, notamment pour Power BI Direct Lake et le SQL analytics endpoint.

Attention cependant : V-Order est desactive par defaut dans les nouveaux workspaces Fabric pour privilegier les performances d'ecriture. A vous de l'activer selon votre cas d'usage :

  • Workload read-heavy (dashboards, reporting) → Activer V-Order
  • Workload write-heavy (ingestion massive, ETL) → Garder desactive

Verifier la configuration V-Order

PYSPARK notebook_check_vorder.py
# Verifier si V-Order est actif dans la session
vorder_status = spark.conf.get('spark.sql.parquet.vorder.default')
print(f"V-Order actif : {vorder_status}")

Activer V-Order pour la session

PYSPARK enable_vorder.py
# Activer V-Order au niveau session (tous les writes seront V-Ordered)
spark.conf.set('spark.sql.parquet.vorder.default', 'true')

# Ou activer au niveau table (plus granulaire)
spark.sql("""
    ALTER TABLE gold.dim_customers
    SET TBLPROPERTIES("delta.parquet.vorder.enabled" = "true")
""")

Activer V-Order a l'ecriture

PYSPARK write_with_vorder.py
# Ecriture ponctuelle avec V-Order, sans changer la config session
df_report.write \
    .format("delta") \
    .mode("overwrite") \
    .option("parquet.vorder.enabled", "true") \
    .saveAsTable("gold.report_monthly_sales")
Performance

V-Order ajoute environ 15% de temps d'ecriture, mais offre 40-60% d'amelioration en lecture pour Power BI Direct Lake et ~10% pour le SQL endpoint. Le trade-off en vaut la peine pour les couches Gold.

03. Tirer parti d'Optimize Write

Optimize Write est une fonctionnalite Delta Lake qui reduit le nombre de fichiers ecrits en consolidant automatiquement les petits fichiers pendant les operations d'ecriture. C'est le premier rempart contre le "small file problem" qui degrade les performances des workloads Big Data.

Bonne nouvelle : dans Fabric, Optimize Write est active par defaut. Vous n'avez rien a configurer. Si vous devez le desactiver temporairement (cas tres rares d'ingestion streaming haute frequence) :

PYSPARK optimize_write_config.py
# Verifier le statut (devrait etre True dans Fabric)
spark.conf.get('spark.databricks.delta.optimizeWrite.enabled')

# Desactiver temporairement si necessaire (rare)
spark.conf.set('spark.databricks.delta.optimizeWrite.enabled', 'false')

# Ou controller par ecriture individuelle
df.write \
    .format("delta") \
    .mode("append") \
    .option("optimizeWrite", "false") \
    .saveAsTable("bronze.raw_events")

04. Lancer OPTIMIZE pour la bin-compaction

Meme avec Optimize Write, des petits fichiers s'accumulent avec le temps (surtout avec des ecritures incrementales). La commande OPTIMIZE consolide ces fichiers en fichiers Parquet plus gros (idealement entre 128 MB et 1 GB), ce qui ameliore considerablement les performances de lecture.

SPARK SQL optimize_tables.sql
-- Optimiser une table complete
OPTIMIZE silver.fact_transactions;

-- Optimiser avec un filtre (plus rapide, cible les partitions recentes)
OPTIMIZE silver.fact_transactions
WHERE ingestion_date >= '2026-02-01';

-- Optimiser + appliquer V-Order en meme temps
OPTIMIZE gold.dim_products VORDER;
Important

Les commandes OPTIMIZE sont des commandes Spark SQL. Elles ne fonctionnent PAS dans le SQL analytics endpoint ou le Warehouse SQL editor (qui n'acceptent que du T-SQL). Utilisez un notebook ou un Spark Job Definition.

05. Nettoyer avec VACUUM

Delta Lake conserve les anciens fichiers Parquet pour supporter le time travel. Avec le temps, ces fichiers orphelins s'accumulent et augmentent les couts de stockage. VACUUM supprime les fichiers qui ne sont plus references par le log Delta et qui depassent la periode de retention.

SPARK SQL vacuum_tables.sql
-- Supprimer les fichiers de plus de 7 jours (defaut)
VACUUM silver.fact_transactions;

-- Specifier une retention personnalisee (en heures)
VACUUM silver.fact_transactions RETAIN 168 HOURS;
Attention

Ne descendez jamais en dessous de 7 jours de retention sans une raison valide. Des lecteurs ou ecrivains concurrents peuvent encore utiliser les anciens fichiers. Un VACUUM trop agressif peut provoquer des erreurs de lecture voire corrompre la table.

06. Utiliser Z-ORDER sur les colonnes filtrees

Z-ORDER reorganise les donnees a l'interieur des fichiers Parquet pour co-localiser les valeurs souvent interrogees ensemble. C'est particulierement efficace sur les colonnes utilisees dans les clauses WHERE et les jointures.

SPARK SQL zorder_optimize.sql
-- Z-ORDER sur une colonne de filtre frequente
OPTIMIZE silver.fact_transactions
ZORDER BY (customer_id);

-- Z-ORDER multi-colonnes + V-Order combines
OPTIMIZE silver.fact_transactions
WHERE ingestion_date >= '2026-02-01'
ZORDER BY (customer_id, product_id) VORDER;

L'ordre des optimisations appliquees par Spark : bin-compactionZ-ORDERV-ORDER. Les trois sont compatibles et se completent.

07. Adopter l'architecture Medallion

L'architecture Medallion (Bronze / Silver / Gold) est le pattern de reference pour structurer vos donnees dans le Lakehouse. Chaque couche a un role precis et des regles d'optimisation differentes :

Couche Role V-Order Optimisation
Bronze Donnees brutes, ingestion rapide Off Append-only, OPTIMIZE hebdo
Silver Donnees nettoyees, conformes Optionnel OPTIMIZE + Z-ORDER quotidien
Gold Aggregats metier, reporting On OPTIMIZE + VORDER apres chaque refresh
PYSPARK medallion_pipeline.py
# ─── BRONZE : Ingestion brute depuis un CSV ───
df_raw = spark.read \
    .format("csv") \
    .option("header", "true") \
    .option("inferSchema", "true") \
    .load("Files/raw/sales_2026.csv")

df_raw.write \
    .format("delta") \
    .mode("append") \
    .saveAsTable("bronze.raw_sales")

# ─── SILVER : Nettoyage et typage ───
df_silver = spark.sql("""
    SELECT
        CAST(sale_id AS INT) AS sale_id,
        CAST(customer_id AS INT) AS customer_id,
        CAST(amount AS DECIMAL(10,2)) AS amount,
        TO_DATE(sale_date, 'yyyy-MM-dd') AS sale_date,
        current_timestamp() AS processed_at
    FROM bronze.raw_sales
    WHERE amount IS NOT NULL AND amount > 0
""")

df_silver.write \
    .format("delta") \
    .mode("overwrite") \
    .saveAsTable("silver.clean_sales")

# ─── GOLD : Agregation metier avec V-Order ───
df_gold = spark.sql("""
    SELECT
        customer_id,
        COUNT(*) AS total_orders,
        SUM(amount) AS total_revenue,
        AVG(amount) AS avg_order_value,
        MAX(sale_date) AS last_purchase_date
    FROM silver.clean_sales
    GROUP BY customer_id
""")

df_gold.write \
    .format("delta") \
    .mode("overwrite") \
    .option("parquet.vorder.enabled", "true") \
    .saveAsTable("gold.customer_metrics")

08. Choisir les bons modes d'ecriture

Le choix entre append, overwrite et merge a un impact direct sur les performances et la maintenance de vos tables :

PYSPARK write_modes.py
# Mode APPEND : ajout incremental (Bronze)
df_new_data.write \
    .format("delta") \
    .mode("append") \
    .saveAsTable("bronze.events")

# Mode OVERWRITE : remplacement complet (Gold / petites tables)
df_aggregated.write \
    .format("delta") \
    .mode("overwrite") \
    .saveAsTable("gold.daily_kpis")

# Mode OVERWRITE partiel avec replaceWhere (Silver / partitions)
df_today.write \
    .format("delta") \
    .mode("overwrite") \
    .option("replaceWhere", "sale_date = '2026-02-25'") \
    .saveAsTable("silver.daily_sales")

09. Exploiter Low Shuffle Merge

Le MERGE (upsert) est essentiel pour les tables de dimension en SCD Type 1. Fabric inclut une optimisation exclusive : le Low Shuffle Merge, qui exclut les lignes non modifiees du shuffle couteux. Cette optimisation est activee par defaut et ne necessite aucune modification de code.

PYSPARK merge_upsert.py
from delta.tables import DeltaTable

# Table cible existante
target = DeltaTable.forName(spark, "silver.dim_customers")

# Source : nouvelles donnees / mises a jour
source = df_new_customers

# MERGE : upsert avec Low Shuffle Merge (actif par defaut)
target.alias("t").merge(
    source.alias("s"),
    "t.customer_id = s.customer_id"
).whenMatchedUpdateAll() \
 .whenNotMatchedInsertAll() \
 .execute()
Astuce

Le Low Shuffle Merge est controle par spark.microsoft.delta.merge.lowShuffle.enabled (active par defaut). Il est compatible avec le Delta Lake open source et ne necessite aucun changement de code.

10. Automatiser la maintenance

Les commandes OPTIMIZE et VACUUM doivent etre executees regulierement. Voici un notebook de maintenance reutilisable que vous pouvez orchestrer avec un Data Pipeline Fabric :

PYSPARK maintenance_job.py
# ═══ Notebook de maintenance automatique ═══
# A orchestrer quotidiennement via Data Pipeline

tables_to_maintain = [
    {"name": "silver.fact_transactions", "zorder": ["customer_id"]},
    {"name": "silver.fact_events",       "zorder": ["event_type"]},
    {"name": "gold.customer_metrics",   "zorder": []},
    {"name": "gold.daily_kpis",         "zorder": []},
]

for table in tables_to_maintain:
    name = table["name"]
    zorder_cols = table["zorder"]

    print(f"Maintenance : {name}")

    # Etape 1 : OPTIMIZE (+ Z-ORDER si applicable)
    if zorder_cols:
        cols = ", ".join(zorder_cols)
        spark.sql(f"OPTIMIZE {name} ZORDER BY ({cols}) VORDER")
    else:
        spark.sql(f"OPTIMIZE {name} VORDER")

    # Etape 2 : VACUUM (retention 7 jours par defaut)
    spark.sql(f"VACUUM {name}")

    print(f"  Done !")

print("Maintenance terminee.")
Alternative no-code

Vous pouvez aussi lancer la maintenance via l'interface Lakehouse : clic droit sur une table → Maintenance → cochez OPTIMIZE, V-Order et/ou VACUUM → Run now. Pratique pour du ponctuel, mais le notebook reste preferable pour l'automatisation.

Σ Recapitulatif

Best Practice Commande / Config Frequence
Format Delta par defaut Automatique dans Fabric -
V-Order (couche Gold) parquet.vorder.enabled A chaque write Gold
Optimize Write Active par defaut Automatique
OPTIMIZE OPTIMIZE table Quotidien / Hebdo
VACUUM VACUUM table Hebdomadaire
Z-ORDER ZORDER BY (col) Avec OPTIMIZE
Architecture Medallion Bronze / Silver / Gold Design initial
Write modes append / overwrite / merge Par cas d'usage
Low Shuffle Merge Actif par defaut Automatique
Maintenance automatisee Notebook + Pipeline Quotidien

En appliquant ces 10 bonnes pratiques, vous construisez un Lakehouse performant, maintenable et optimise pour tous les moteurs analytiques de Fabric. La cle est d'adapter les strategies d'optimisation a chaque couche de votre architecture Medallion.

Si vous avez des questions ou souhaitez echanger sur Microsoft Fabric, n'hesitez pas a me contacter sur LinkedIn.

Sources & References