Les familles NoSQL
Ce que ce chapitre apporte
- Expliquer le renversement de méthode : modéliser à partir des accès plutôt que des entités.
- Décrire les quatre familles dans leur organisation et leur cas d'usage.
- Distinguer une base orientée colonnes d'un stockage en colonnes, que le vocabulaire confond.
- Justifier une dénormalisation et en énoncer le prix.
- Choisir un type de stockage à partir d'un besoin métier, et savoir dire ce qu'on abandonne.
Le modèle relationnel range les données selon ce qu'elles sont, une fois pour toutes, et laisse le moteur trouver comment répondre. Les bases dites NoSQL renversent l'ordre : elles rangent les données selon les questions qu'on leur posera, et acceptent de mal répondre à toutes les autres. Ce renversement explique leurs quatre familles, leurs performances, et le prix qu'elles font payer.
Le sigle est un accident historique. Il ne signifie pas « sans SQL », puisque plusieurs de ces bases proposent un langage qui y ressemble beaucoup, mais pas seulement SQL : la reconnaissance qu'un modèle unique ne convient pas à tous les usages.
Ce qui distingue réellement ces bases n'est ni le langage ni l'absence de schéma, mais une décision de modélisation prise à l'envers de l'habitude.
Le renversement de méthode
La démarche relationnelle part des entités et de leurs liens, élimine les redondances par la normalisation, et obtient un schéma qui décrit fidèlement le domaine. Les questions viennent ensuite, et le moteur se débrouille : n'importe quelle jointure reste possible, même celle que personne n'avait prévue.
La démarche NoSQL part des accès. On liste les questions que l'application posera, leur fréquence et leur exigence de temps de réponse, puis on range les données de façon que chacune se satisfasse en une seule lecture au même endroit. Une question non prévue devient coûteuse, voire impossible sans tout relire.
Un schéma relationnel bien normalisé absorbe une question nouvelle sans modification : il suffit d'écrire une autre requête.
Un modèle construit pour trois accès n'en absorbe pas un quatrième. Il faut réorganiser les données, donc les réécrire toutes, donc prévoir une migration sur des volumes qui sont précisément ceux qui avaient motivé le choix.
La question à se poser avant de renoncer au relationnel n'est donc pas « ai-je beaucoup de données ? » mais « mes accès sont-ils stables et connus ? ». Sur un domaine encore mouvant, le relationnel reste souvent le meilleur choix, même à grande échelle.
Clé-valeur
Une base clé-valeur est un dictionnaire réparti : une clé, une valeur, et deux opérations, lire et écrire.
La valeur est opaque pour la base, qui ne l'inspecte jamais. Il n'existe donc aucune requête portant sur son contenu, aucun index secondaire, aucune jointure.
C'est le modèle le plus pauvre et le plus rapide. Comme la clé détermine seule l'emplacement, la base sait immédiatement quel nœud interroger, sans consulter aucun index : une lecture coûte un aller-retour réseau, quel que soit le nombre de clés stockées.
Ses usages découlent de cette pauvreté même : sessions d'utilisateurs, cache de résultats, paniers d'achat, compteurs, files d'attente. Chaque fois qu'on sait exactement quoi demander, et qu'on ne demandera jamais autre chose.
Comme la base n'inspecte pas les valeurs, toute la structure passe dans la clé, sous forme de conventions : session:8f3a, panier:u1234, stats:2024-03:ventes.
Ces conventions ne sont vérifiées par rien. Une faute de frappe crée une clé nouvelle au lieu de signaler une erreur, et la donnée attendue reste introuvable sans que rien n'échoue.
La discipline consiste à centraliser la fabrication des clés dans une seule fonction du code, jamais à les écrire à la main sur les sites d'appel.
Orientée documents
Une base orientée documents stocke des documents structurés, généralement en JSON, regroupés en collections. Contrairement à la valeur d'une base clé-valeur, le document est inspectable : la base sait lire ses champs, les indexer, et filtrer dessus.
Chaque document est autonome et contient tout ce qu'une lecture demande, y compris ce qui serait, en relationnel, réparti dans plusieurs tables.
C'est ici que la dénormalisation prend tout son sens. Une commande relationnelle vit dans trois tables, commande, ligne_commande et produit, et se lit par deux jointures. Le même objet, en document, tient dans un seul enregistrement contenant ses lignes et le libellé des produits, et se lit en une fois.
Dupliquer le libellé d'un produit dans chaque commande supprime une jointure à chaque lecture, et impose de réécrire toutes les commandes concernées à chaque changement de libellé.
L'échange est excellent quand les lectures sont mille fois plus nombreuses que les écritures, ce qui est le cas ordinaire d'un catalogue ou d'un historique. Il est désastreux dans le cas inverse.
Une nuance souvent oubliée : sur une commande, le libellé et le prix dupliqués ne sont pas une redondance, ce sont les valeurs au moment de l'achat. Les recopier est alors juste sur le fond, indépendamment de toute considération de performance, et le relationnel le ferait aussi.
Une collection de documents accepte des documents de formes différentes. Cela ne veut pas dire qu'il n'y a pas de schéma : il y en a un, celui que le code de lecture suppose, et il n'est simplement vérifié nulle part.
Le schéma existe donc, dispersé dans l'application, et il dérive avec le temps. Un champ renommé laisse coexister deux générations de documents, et le code doit gérer les deux, indéfiniment, faute d'une migration que rien n'impose.
L'absence de schéma est un gain à l'écriture et une dette à la lecture. Les bases documentaires sérieuses proposent d'ailleurs une validation optionnelle, qu'il faut activer.
Orientée colonnes
Une base orientée colonnes, au sens NoSQL, range les données par ligne identifiée par une clé, chaque ligne pouvant porter un très grand nombre de colonnes, différentes d'une ligne à l'autre, regroupées en familles.
L'accès efficace se fait par la clé de ligne, et par plages de clés consécutives, ce qui en fait le modèle naturel des séries chronologiques : une clé composée d'un identifiant de capteur et d'un horodatage permet de lire d'un coup toutes les mesures d'une journée.
Le vocabulaire est malheureux et la confusion est générale.
Une base orientée colonnes au sens NoSQL est un modèle de données : des lignes à colonnes variables, interrogées par clé.
Un stockage en colonnes est un format de fichier : les valeurs d'une même colonne sont écrites côte à côte sur le disque, au lieu de l'être ligne par ligne. Cela permet de ne lire que les colonnes utiles à une requête, et de très bien compresser puisque des valeurs voisines se ressemblent. C'est le principe des formats analytiques employés dans les entrepôts.
Les deux notions sont indépendantes : une base relationnelle peut employer un stockage en colonnes, et une base orientée colonnes peut écrire ses fichiers par lignes. Confondre les deux conduit à choisir un modèle de données pour obtenir une propriété de format, ce qui ne marche pas.
Orientée graphes
Une base orientée graphes stocke des nœuds et des relations, les deux pouvant porter des propriétés. La relation est un objet de première classe, physiquement matérialisée : parcourir un lien coûte le même prix quel que soit le nombre total de nœuds.
C'est la seule famille dont la justification n'est pas la mise à l'échelle mais l'expressivité. Le relationnel sait représenter un graphe, avec une table d'arêtes ; il sait mal l'interroger sur plusieurs niveaux, car chaque saut ajoute une jointure et le coût explose en profondeur.
Chaque trait se lit « a acheté ». Le parcours mis en évidence part de Zoé, passe par un produit qu'elle possède, remonte vers un autre client, et redescend vers un produit qu'elle n'a pas : c'est la recommandation, et elle tient en trois arêtes.
La recommandation « les clients qui ont acheté ce que vous avez acheté ont aussi acheté » est un parcours de trois arêtes. En relationnel, c'est une triple jointure sur une table d'achats. Sur trois niveaux la différence est mince ; sur six, elle devient un facteur mille.
Les usages suivent : détection de fraude par cycles de transactions, recommandation, réseaux sociaux, dépendances logicielles, cheminements dans un réseau. Chaque fois que la question porte sur la forme des liens et non sur les valeurs.
Les trois autres familles se découpent naturellement : une clé détermine un nœud, et la question suivante s'y trouve entièrement.
Un graphe n'a pas cette propriété. Découper un graphe en morceaux revient à couper des arêtes, et chaque arête coupée devient un aller-retour réseau au milieu d'un parcours. Le problème de la coupe minimale est difficile, et les données réelles s'y prêtent mal puisque quelques nœuds concentrent l'essentiel des liens.
C'est pourquoi les bases orientées graphes tiennent souvent sur une machine unique, et pourquoi elles se justifient par l'expressivité plutôt que par le volume.
Choisir
| Famille | Organisation | Interrogée par | Bonne pour | Mauvaise pour |
|---|---|---|---|---|
| Clé-valeur | dictionnaire réparti | la clé, uniquement | sessions, cache, compteurs | toute question sur le contenu |
| Documents | documents autonomes | la clé et les champs indexés | objets métier lus en entier | croisements imprévus, transactions larges |
| Colonnes | lignes à colonnes variables | la clé et les plages de clés | séries chronologiques, historiques massifs | requêtes ne portant pas sur la clé |
| Graphes | nœuds et relations | le parcours des liens | fraude, recommandation, réseaux | volume au-delà d'une machine |
| Relationnel | tables normalisées | n'importe quelle requête | accès non stabilisés, transactions | débit d'écriture extrême, schéma très variable |
Quelles sont les questions, et sont-elles stables ? Si elles ne le sont pas, le relationnel garde l'avantage, quel que soit le volume.
Une question se satisfait-elle avec une seule clé ? Si oui, clé-valeur ou documents. Si elle porte sur une plage de clés ordonnées, colonnes. Si elle porte sur la forme des liens, graphes.
Quel est le rapport entre lectures et écritures ? Il décide de tout ce qui touche à la dénormalisation, et c'est le chiffre que personne ne mesure avant de choisir.
Une application sérieuse emploie couramment plusieurs stockages : le relationnel pour les données transactionnelles, une base clé-valeur pour les sessions, un entrepôt pour l'analyse.
Cette diversité a un prix qu'il faut assumer : chaque stockage supplémentaire ajoute une exploitation, une sauvegarde, une compétence, et un risque d'incohérence entre les copies d'une même information. Multiplier les technologies pour le plaisir de la nouveauté est la faute la plus répandue du domaine.
La règle raisonnable : n'ajouter un stockage que lorsqu'un besoin mesuré ne peut pas être satisfait par ceux déjà en place.
Exercices type
Exercice 1 : une plateforme enregistre les mesures de 50 000 capteurs, chacun émettant une valeur par minute. Les questions posées sont toujours de la forme « les mesures du capteur X entre telle et telle date ». Quel stockage ?
Afficher la solution
Une base orientée colonnes, avec une clé composée de l'identifiant du capteur suivi de l'horodatage.
Les lignes d'un même capteur deviennent consécutives, et une plage de dates se lit d'un seul balayage, sans index secondaire ni tri.
C'est le cas d'école de cette famille, et le volume le confirme : 50 000 capteurs à une mesure par minute font 72 millions de mesures par jour, soit environ 26 milliards par an. Aucune table relationnelle indexée ne tient ce rythme à ce prix.
Le point de vigilance est la clé : la placer dans l'ordre inverse, horodatage puis capteur, concentrerait toutes les écritures d'un instant sur un seul nœud, exactement le déséquilibre du chapitre sur le découpage.
Exercice 2 : une équipe veut passer une application de gestion en base documentaire « parce que le relationnel ne passe pas à l'échelle ». Le volume est de 40 gigaoctets et les besoins d'analyse changent tous les mois. Que répondre ?
Afficher la solution
Que le raisonnement inverse deux choses.
40 gigaoctets ne posent aucun problème d'échelle à une base relationnelle : c'est un volume que gère une seule machine correctement dimensionnée, avec des index et sans effort particulier.
Et surtout, des besoins qui changent tous les mois sont l'argument le plus fort contre un modèle orienté accès. Chaque nouveau besoin exigerait une réorganisation des documents et une réécriture des données existantes.
S'il y a une lenteur, elle vient probablement d'un index absent ou d'une requête écrite avec un parcours imbriqué, et elle se corrige là où elle est.
Exercice 3 : dans une base documentaire, faut-il dupliquer le libellé d'un produit dans chaque ligne de commande ?
Afficher la solution
Oui, et pour deux raisons de nature différente qu'il faut distinguer.
La raison de performance : cela supprime un accès par produit à chaque lecture de commande, et une commande se lit bien plus souvent qu'un libellé ne change.
La raison de justesse, plus forte : une commande doit conserver le libellé et le prix au moment de l'achat. Ce ne sont pas des copies du catalogue, ce sont des faits historiques. Une base relationnelle bien conçue les recopierait aussi, et ce n'est donc pas une dénormalisation mais une modélisation correcte.
La duplication est problématique quand elle recopie une valeur qui doit rester unique et à jour, comme l'adresse courante d'un client.
Exercice 4 : un service de détection de fraude cherche des cycles de transactions entre comptes, de longueur trois à six. Le volume est de 200 millions de transactions. Quel stockage, et quelle difficulté ?
Afficher la solution
Une base orientée graphes, car la question porte sur la forme des liens et non sur les valeurs : chercher un cycle de longueur six en relationnel demande six jointures dont le coût devient inabordable.
La difficulté est celle de la section précédente : 200 millions de transactions dépassent probablement ce qu'une machine unique traite confortablement, et un graphe se répartit mal.
Deux issues courantes. Restreindre le graphe avant de l'interroger, en ne conservant que les comptes et les périodes suspects selon des critères simples, ce qui ramène le volume à une taille tenant sur une machine. Ou détecter les cycles par un traitement réparti périodique, en acceptant de ne pas répondre en temps réel.
1.Que signifie le sigle NoSQL ?
2.Quelle est la différence essentielle de méthode avec le relationnel ?
3.Une base orientée colonnes et un stockage en colonnes, c'est…
4.Pourquoi une base orientée graphes se répartit-elle mal ?
5.Dupliquer le prix d'un produit dans une ligne de commande est…
6.Quel argument plaide le plus fortement pour garder le relationnel ?
La méthode
- Lister les questions avant les entités, avec leur fréquence et le temps de réponse exigé.
- Vérifier que ces questions sont stables : c'est le critère qui décide, avant le volume.
- Mesurer le rapport lectures sur écritures, chiffre qui commande toute décision de dénormalisation.
- Distinguer la duplication de performance de la duplication de justesse : un prix historique n'est pas une redondance.
- Centraliser la fabrication des clés dans une seule fonction, dès qu'un modèle repose sur des conventions de nommage.
- Activer la validation de schéma quand la base la propose, plutôt que de laisser le schéma se disperser dans le code.
- Ne pas confondre modèle orienté colonnes et format de stockage en colonnes.
- N'ajouter un stockage que lorsqu'un besoin mesuré résiste à ceux déjà en place.
Synthèse
- NoSQL signifie « pas seulement SQL », et désigne une méthode de modélisation, pas un langage.
- Le relationnel modélise les entités, les autres familles modélisent les accès.
- Une question imprévue est absorbée gratuitement par le relationnel, et coûte une réécriture ailleurs.
- Clé-valeur : un dictionnaire réparti, valeur opaque, une lecture par clé et rien d'autre.
- Dans une base clé-valeur, la clé devient le schéma, et rien ne la vérifie.
- Documents : des objets autonomes et inspectables, qui suppriment les jointures de lecture.
- La dénormalisation échange des écritures contre des lectures, et ne vaut que si le rapport le justifie.
- « Sans schéma » veut dire « schéma à la lecture » : il existe, dispersé dans le code, et il dérive.
- Colonnes : des lignes à colonnes variables lues par plages de clés, modèle naturel des séries chronologiques.
- Une base orientée colonnes et un stockage en colonnes sont deux notions sans rapport.
- Graphes : la relation est matérialisée, et un parcours coûte le même prix quelle que soit la taille.
- Un graphe se répartit mal : sa justification est l'expressivité, pas le volume.
- Trois questions tranchent : les accès sont-ils stables, une clé suffit-elle, quel est le rapport lectures sur écritures.
- Le choix n'est pas exclusif, et chaque stockage supplémentaire se paie en exploitation.