Traitement Transactionnel et Analytique Hybride (HTAP) : Élimination des pipelines ETL avec Azure Synapse Link et Cosmos DB

09 juil. 2026

Traitement Transactionnel et Analytique Hybride (HTAP) : Élimination des pipelines ETL avec Azure Synapse Link et Cosmos DB

Les pipelines de données traditionnels (ETL) introduisent un décalage temporel inacceptable entre le moment où une transaction est enregistrée dans la base de données opérationnelle et celui où cette information devient visible pour les algorithmes analytiques. Les tentatives de réduction de cette latence en sondant activement les bases de données relationnelles dégradent les performances transactionnelles (OLTP) en raison des blocages de tables et de l’épuisement des ressources CPU. La construction de réseaux de messagerie complexes pour contourner ce goulot d’étranglement exige une maintenance continue et génère une dette technique considérable. L’adoption de l’architecture de traitement transactionnel et analytique hybride (HTAP) via Azure Synapse Link pour Azure Cosmos DB élimine ces déficiences de manière systémique. En activant le Analytical Store, l’infrastructure de Microsoft partitionne les données en coulisses, conservant un stockage orienté lignes pour l’application avec une latence en millisecondes et un stockage en colonnes optimisé pour les agrégations analytiques. Cette topologie permet à des charges de travail analytiques intensives d’interroger les données opérationnelles en quasi-temps réel sans consommer une seule Unité de Requête (RU/s) du provisionnement transactionnel.

Pré-requis

Le déploiement de cette fondation de données exige une maîtrise approfondie de la modélisation NoSQL et des moteurs de traitement massivement parallèles (MPP). L’infrastructure doit être codifiée de manière déterministe via Terraform version 1.7.0 ou supérieure associée au fournisseur HashiCorp AzureRM version 3.90.0 ou supérieure. La couche d’ingestion nécessite Python 3.12 avec le SDK azure-cosmos (version 4.3.0), tandis que la couche analytique utilisera l’API PySpark (version 3.4) au sein d’Azure Synapse Analytics. Des privilèges administratifs sur l’abonnement Azure sont obligatoires pour activer le réseau géré du Synapse Workspace et autoriser le passage des données d’entreprise.

Étapes

Provisionnement du Répositoire Dual (Row Store et Column Store)

La fondation du standard HTAP exige le provisionnement d’une base NoSQL avec support explicite pour le mirroring en colonnes automatique. Nous configurons un compte Azure Cosmos DB et créons des conteneurs en activant la propriété analytical_storage_enabled. L’argument architectural clé réside dans la séparation physique des charges de travail. Par défaut, Cosmos DB stocke les documents dans un format orienté lignes (Row Store) indexé, ce qui assure des lectures et écritures ponctuelles efficaces pour l’application. Toutefois, balayer des millions de lignes pour calculer des moyennes financières consomme des ressources de calcul prohibitifs. En activant le stockage analytique, l’infrastructure opère un processus de synchronisation invisible qui extrait les insertions, mises à jour et suppressions de la couche transactionnelle et les convertit en format colonne (Parquet) dans un espace de stockage parallèle. Ce processus s’exécute de manière autonome, ne concurrence pas les ressources allouées à la base principale et n’affecte pas la latence de l’API côté client.

resource "azurerm_cosmosdb_account" "htap_account" {
  name                = "cosmos-enterprise-htap"
  location            = var.location
  resource_group_name = var.resource_group_name
  offer_type          = "Standard"
  kind                = "GlobalDocumentDB"

  consistency_policy {
    consistency_level = "Session"
  }

  geo_location {
    location          = var.location
    failover_priority = 0
  }

  # Habilite l’analytical storage sur le compte
  enable_analytical_storage = true
}

resource "azurerm_cosmosdb_sql_database" "commerce_db" {
  name                = "CommerceDB"
  resource_group_name = azurerm_cosmosdb_account.htap_account.resource_group_name
  account_name        = azurerm_cosmosdb_account.htap_account.name
}

resource "azurerm_cosmosdb_sql_container" "orders_container" {
  name                  = "Orders"
  resource_group_name   = azurerm_cosmosdb_account.htap_account.resource_group_name
  account_name          = azurerm_cosmosdb_account.htap_account.name
  database_name         = azurerm_cosmosdb_sql_database.commerce_db.name
  partition_key_paths   = ["/tenantId"]
  partition_key_version = 2
  
  # Durée de rétention des données transactionnelles (Row Store) en secondes (-1 = infinie)
  default_ttl = -1
  
  # Durée de rétention analytique isolée
  analytical_storage_ttl = -1
}

Comment injecter le flux continu de transactions commerciales dans ce conteneur tout en garantissant que les schémas dynamiques ne perturbent pas la structure en colonnes générée en coulisses par le moteur Azure?

Ingestion Transactionnelle et Évolution du Schéma (Schéma Inference)

L’ingestion des données (OLTP) se fait de manière native et sans dépendre de la couche analytique, en utilisant le SDK standard de Cosmos DB. L’application écrit des documents JSON avec des structures variées, adhérant au principe NoSQL sans schéma préétabli (schema-less). Le raisonnement technique qui permet la transformation mathématique de ces documents amorphes en colonnes typées est l’Inférence de Schéma Rigide (Schema Inference) intégrée au Synapse Link. Le moteur Azure parcourt les propriétés des documents et crée des colonnes dans le stockage analytique. Si l’application envoie d’abord un entier dans le champ total_amount, puis envoie une chaîne pour le même champ, le moteur HTAP créera deux colonnes distinctes au format colonne (par exemple total_amount_int64 et total_amount_string), évitant ainsi l’échec du pipeline et permettant aux ingénieurs de données de résoudre l’anomalie par des transformations (casting) lors de la requête.

import os
import uuid
import time
import logging
from typing import Dict, Any
from azure.cosmos import CosmosClient, PartitionKey
from azure.identity import DefaultAzureCredential

logger = logging.getLogger("OltpAdapter")

class TransactionalIngestionAdapter:
    def __init__(self, endpoint: str):
        credential = DefaultAzureCredential()
        self.client = CosmosClient(endpoint, credential=credential)
        self.database = self.client.get_database_client("CommerceDB")
        self.container = self.database.get_container_client("Orders")

    def record_sale(self, tenant_id: str, amount: float, items: list) -> None:
        document_id = str(uuid.uuid4())
        
        # Le document est stocké dans le Row Store en millisecondes.
        # L’infrastructure d’Azure le projettera dans le Column Store en moins de 2 minutes.
        payload = {
            "id": document_id,
            "tenantId": tenant_id,
            "amount": amount,
            "items": items,
            "transaction_timestamp": int(time.time()),
            "status": "COMPLETED"
        }
        
        self.container.create_item(body=payload)
        logger.info(f"Transaction {document_id} enregistrée dans le stockage OLTP.")

adapter = TransactionalIngestionAdapter(os.environ["COSMOS_ENDPOINT"])
adapter.record_sale("tenant_alpha", 1500.50, [{"sku": "NTBK-01", "qty": 1}])

Puisque la barrière ETL est levée et que les données opérationnelles sont disponibles sous forme de colonnes, comment mettre en œuvre le calcul dans le cloud pour traiter des péta-octets d’informations et en extraire une valeur analytique sans déployer des clusters inactifs 24 heures sur 24?

Analyse Massive avec des Pools Spark éphémères (Synapse Workspace)

Nous exécutons les charges analytiques en instanciant des Notebooks et des Pools Apache Spark directement dans Azure Synapse Analytics, en les connectant au Cosmos DB Analytical Store. L’architecture nécessite un Service Lié (Linked Service) qui établit un trajet direct entre le Synapse Workspace et Cosmos DB en utilisant des identités gérées. L’enjeu crucial réside dans l’isolement des coûts et des performances. Le code PySpark ci-dessous effectue des agrégations complexes sur l’ensemble des commandes enregistrées. Il lit directement les fichiers Parquet sous-jacents au Cosmos DB (Analytical Store). La transaction n’accède jamais aux index transactionnels et ne consomme donc aucune RU/s. De plus, les Pools Spark dans le Synapse sont éphémères et configurables avec arrêt automatique (auto-pause) ; ils se réveillent, traitent les données opérationnelles de l’heure précédente et se mettent en veille, ne facturant que les minutes de calcul effectivement utilisées pour l’agrégation.

# Code exécuté dans un Notebook PySpark au sein d’Azure Synapse Analytics
from pyspark.sql.functions import col, sum, window
import time

# Le Service Lié gère l’authentification sous-jacente
cosmos_format = "cosmos.olap"
linked_service_name = "CosmosDbHtapLink"
database_name = "CommerceDB"
container_name = "Orders"

print("Lecture massive directement depuis l’Analytical Store (sans consommation de RU/s)…")

# La lecture cible le moteur OLAP intégré
df = spark.read.format(cosmos_format) 
    .option("spark.synapse.linkedService", linked_service_name) 
    .option("spark.cosmos.container", container_name) 
    .load()

# Agrégation haute performance traitée en mémoire sur le cluster Spark
# Analyse du chiffre d’affaires total par tenant
agg_df = df.filter(col("status") == "COMPLETED") 
    .groupBy("tenantId") 
    .agg(sum("amount").alias("TotalRevenue"))

agg_df.show()

# Facultativement, le résultat peut être enregistré dans le Data Lake (Parquet)
# pour consommation par des outils BI tels que Power BI.

Si la base de données principale accumule des données indéfiniment, les coûts de stockage augmentent proportionnellement, mais supprimer les enregistrements anciens dans l’application effacera l’historique des outils BI. Comment concevons-nous le cycle de vie de l’information pour protéger le modèle analytique tout en réduisant les coûts opérationnels?

Governance et Cycle de Vie Asynchrone (ATTL vs TTTL)

Nous résolvons le conflit de rétention en dissociant mathématiquement la durée de vie transactionnelle (TTTL) de la durée de vie analytique (ATTL). Azure Cosmos DB HTAP permet à l’ingénierie de configurer des limites d’expiration indépendantes au niveau du conteneur. L’objectif architectural est l’optimisation du coût de stockage dynamique (Hot Storage). L’application frontale interroge rarement des transactions plus anciennes que 90 jours directement depuis l’API principale. Par conséquent, Terraform est mis à jour pour configurer le default_ttl (Transactional Time-to-Live) à 7 776 000 secondes (90 jours). Parallèlement, nous configurons le analytical_storage_ttl à -1 (infinis) ou à une période réglementaire longue, comme 5 ans. Lorsqu’un enregistrement atteint 90 jours, le moteur OLTP l’efface silencieusement de l’index des lignes, libérant de l’espace disque coûteux. Toutefois, l’enregistrement demeure intact dans le stockage en colonnes moins coûteux (Analytical Store). Cela préserve l’historique pour des modèles d’apprentissage automatique sur Synapse, tout en optimisant le budget cloud sans nécessiter de déplacement manuel des données (archivage sur bande).

Dépannage courant

Un obstacle persistant dans l’intégration des Synapse Workspaces avec Cosmos DB protégé (VNet restreinte) se manifeste par des exceptions 403 Forbidden dans les Notebooks Spark lors d’une tentative de lecture. Cela se produit même si l’Identité gérée de Synapse a été ajoutée au rôle Cosmos DB Built-in Data Contributor. L’anomalie réside dans l’incapacité du Synapse Serverless (ou Spark) à traverser le pare-feu Cosmos DB via l’internet public lorsque la règle « Allow Access from Azure Services » est désactivée et qu’un Private Endpoint n’a pas été configuré. La mitigation technique exige le provisionnement d’un Managed Private Endpoint spécifiquement dans le Synapse Studio, pointant vers Azure Cosmos DB. Après la création, un administrateur doit approuver manuellement la connexion privée dans le portail Cosmos DB afin de sceller la communication sur le backbone réseau fermé de Microsoft.

Une autre lacune analytique apparaît lorsque les agrégations Spark retournent des décomptes incohérents juste après des pics d’écriture agressifs. L’ingénieur observera que des transactions enregistrées il y a dix secondes ne figurent pas dans le dataframe agrégé. Cette condition est un comportement délibéré par conception. Le processus d’isolation entre le Row Store et le Column Store n’est pas synchrone. Il existe un retard autonome et non configurables pouvant atteindre cinq minutes (souvent moins de deux) géré par Microsoft pour regrouper et convertir les documents JSON en colonnes Parquet de manière efficace. Le système délivre un quasi-temps réel (Near Real-Time). Les architectures nécessitant des déclencheurs de latence en dessous de la milliseconde doivent recourir au Change Feed (OLTP) couplé à Azure Functions, en réservant le Synapse Link (OLAP) exclusivement pour les découvertes massives de données qui supportent une tolérance temporelle dans la plage des minutes.

Conclusion

L’architecture de traitement transactionnel et analytique hybride remplace la complexité imposée par la construction de pipelines ETL par l’abstraction déclarative offerte par la plateforme cloud. Isoler les moteurs de traitement pendant que la couche de stockage sous-jacente se sincronise de manière autonome garantit que l’exploration scientifique des données n’exige pas de refactorisations agressives dans le domaine transactionnel. Cette topologie accélère le cycle de vie du développement des données opérationnelles. Dans des écosystèmes multicloud en évolution au sein des entreprises, le modèle HTAP conceptuel reflète les fonctionnalités offertes par AWS Supernova (Amazon Aurora s’intégrant sans limites à Amazon Redshift Zero-ETL), consolidant la convergence universelle entre les volets opérationnels et l’intelligence d’entreprise.

Fabien Delpont

Auteur

Fabien Delpont

Fabien Delpont, développeur et créateur du site Python Doctor.