OLTP vs OLAP et stockage en colonnes
Résumé
Une base transactionnelle (OLTP) sert une application : beaucoup de petites lectures et écritures sur quelques lignes à la fois. Une base analytique (OLAP) sert des questions : peu de requêtes, chacune lit beaucoup de lignes mais peu de colonnes. Ces deux charges favorisent deux dispositions physiques opposées. Le stockage en lignes garde tous les champs d’une ligne côte à côte, ce qui convient à la recherche d’un enregistrement. Le stockage en colonnes garde chaque colonne séparément, ce qui convient à l’agrégation sur des millions de lignes. Beaucoup d’erreurs de coût ou de performance en analytique viennent d’avoir oublié cette différence.
Prérequis
Savoir ce qu’est une table et une requête d’agrégation (
SUM,GROUP BY). Aucune autre note n’est nécessaire.
Deux charges de travail
| OLTP (online transaction processing) | OLAP (online analytical processing) | |
|---|---|---|
| Question type | « Quel est le solde du compte 4217 ? » | « Quel est le chiffre d’affaires par région et par mois sur trois ans ? » |
| Lignes touchées par requête | Une ou quelques-unes | Des millions |
| Colonnes lues | Presque toutes | Quelques-unes |
| Écritures | Fréquentes, petites, transactionnelles | Chargements par lots, ou flux |
| Garantie attendue | Transactions fiables : ACID vs BASE | Cohérence d’un instantané lisible |
| Modèle de données | Normalisé : Normalisation 2NF et 3NF | Souvent dénormalisé ou dimensionnel : Inmon, Kimball et Data Vault |
| Exemples | PostgreSQL, MySQL, Oracle (usage applicatif) | BigQuery, Snowflake, ClickHouse, DuckDB |
Les deux charges se mélangent mal sur le même système : une grosse agrégation bloque des transactions courtes, et un modèle normalisé multiplie les jointures coûteuses pour l’analyse. D’où la séparation habituelle : la base applicative alimente un entrepôt analytique (voir Staging, ODS, DWH et architecture médaillon).
Lignes ou colonnes
Prenons une table de commandes de 100 millions de lignes et 20 colonnes, que l’on suppose de 8 octets chacune pour simplifier.
flowchart LR subgraph L["Stockage en lignes"] L1["ligne 1 : id, date, client, montant, …"] L2["ligne 2 : id, date, client, montant, …"] L3["ligne 3 : …"] end subgraph C["Stockage en colonnes"] C1["colonne id : 1, 2, 3, …"] C2["colonne date : …"] C3["colonne montant : 12, 40, 7, …"] end
| Requête | Stockage en lignes | Stockage en colonnes |
|---|---|---|
SELECT * FROM commandes WHERE id = 4217 | Une lecture : tous les champs de la ligne sont contigus | Il faut recomposer la ligne à partir de 20 colonnes |
SELECT SUM(montant) FROM commandes | Lit chaque ligne en entier : 100 M × 20 × 8 octets, soit environ 16 Go | Lit la seule colonne montant : 100 M × 8 octets, soit environ 0,8 Go |
Les 16 Go et 0,8 Go sont un calcul illustratif sans compression ; l’ordre de grandeur (un facteur de l’ordre du nombre de colonnes) est ce qu’il faut retenir.
La documentation de BigQuery décrit la même idée : les bases en lignes sont efficaces pour retrouver un enregistrement, mais moins pour des fonctions analytiques sur beaucoup d’enregistrements, parce qu’il faut lire tous les champs. BigQuery stocke chaque colonne séparément, ce qui l’avantage pour parcourir une colonne sur tout un jeu de données.1
Deux autres effets du stockage en colonnes
- Meilleure compression. Les valeurs d’une même colonne se ressemblent plus que les valeurs d’une même ligne. Des techniques comme l’encodage par plages (run-length encoding) en profitent, ce qui réduit les octets lus.1
- Statistiques par colonne. Un format colonnaire peut garder des valeurs minimale et maximale par column chunk, ce qui permet de sauter des blocs entiers. Voir Parquet, le format de fichier colonnaire.
Ce que ça change en pratique
Règles qui en découlent
- Éviter
SELECT *sur un moteur colonnaire. Chaque colonne ajoutée à la requête ajoute des octets lus, et sur BigQuery en mode à la demande, des octets facturés.- Filtrer sur la partition quand la table est partitionnée : on lit moins de blocs.
- Ne pas utiliser un entrepôt comme base applicative. Chercher une ligne par identifiant ou mettre à jour une ligne à la fois est le cas défavorable du stockage en colonnes.
- Interroger une table « large » (beaucoup de colonnes) n’est pas un problème en colonnes tant que la requête n’en lit que quelques-unes. Voir Union all vs unpivot pour un cas où cette nuance compte.
Ce n'est pas binaire
Des systèmes hybrides existent (stockage mixte, ou deux copies de la donnée, une par charge). Les limites évoluent ; vérifier ce que fait réellement le produit utilisé plutôt que de se fier à son étiquette.
Notes liées
- Normalisation 2NF et 3NF : le modèle adapté à l’OLTP.
- Inmon, Kimball et Data Vault : les modèles adaptés à l’OLAP.
- Parquet, le format de fichier colonnaire : le stockage en colonnes sous forme de fichier.
- Union all vs unpivot : une conséquence sur le coût d’une requête BigQuery.
- Glossaire data engineering : moteur colonnaire.
- MOC Data Engineering : carte du vault.
Notes de bas de page
-
Overview of BigQuery storage, section « Storage layout », documentation Google Cloud consultée le 24 octobre 2026. ↩ ↩2