La modélisation de données est un processus qui cartographie entités, attributs et relations avant de décider comment la base de données les stockera. Les entités sont la partie facile — chaque produit connaît ses utilisateurs, ses commandes et ses posts. Le vrai métier est dans les relations : quels enregistrements pointent vers lesquels, combien, et où cette arête vit physiquement. Réussissez les arêtes et les requêtes s’écrivent toutes seules ; ratez-les et chaque feature se bat contre le schéma.
Points clés
| Question | Réponse |
|---|---|
| Les trois niveaux | Conceptuel (quoi) → logique (structure) → physique (moteur) |
| Les trois arêtes | Un-à-un · un-à-plusieurs · plusieurs-à-plusieurs |
| Outils relationnels | Clés étrangères ; tables de jointure pour le plusieurs-à-plusieurs |
| Outils documentaires | Embarquement, Pointers (références), Relations/tableaux d’ID |
| La règle moderne | Modélisez pour les patterns d’accès — ce qui se lit ensemble vit ensemble |
Les mêmes relations, dans les deux mondes
Le relationnel d’abord — la clé étrangère porte l’un-à-plusieurs, et le plusieurs-à-plusieurs doit se décomposer via une table de jointure :
-- 1:N — la clé étrangère vit du côté "plusieurs"
CREATE TABLE books (
id bigint PRIMARY KEY,
title text NOT NULL,
author_id bigint NOT NULL REFERENCES authors(id) ON DELETE CASCADE
);
-- M:N — aucune FK seule ne peut l'exprimer ; une table de jointure contient les deux clés
CREATE TABLE book_genres (
book_id bigint REFERENCES books(id),
genre_id bigint REFERENCES genres(id),
added_at timestamptz DEFAULT now(), -- les tables de jointure portent des attributs
PRIMARY KEY (book_id, genre_id) -- clé composite : une arête, une seule fois
);
Côté documentaire, même modèle : l’arête un-à-plusieurs est un Pointer typé, l’arête plusieurs-à-plusieurs est une Relation — aucune table de jointure à inventer, et l’arête se déclare dans le code applicatif :
// JavaScript / Node.js — Back4app JS SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
const author = await new Parse.Query('Author').get(authorId);
const book = new Parse.Object('Book');
book.set('title', 'Dune');
book.set('author', author); // Pointer — typed one-to-many edge
await book.save();
const genres = book.relation('genres'); // Relation — many-to-many, unbounded
genres.add([sciFi, classics]);
await book.save(); // Flutter / Dart — Back4app Flutter SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
final book = ParseObject('Book')
..set('title', 'Dune')
..set('author', author.toPointer()); // Pointer — typed one-to-many edge
await book.save();
book.addRelation('genres', [sciFi, classics]); // Relation — many-to-many
await book.save(); // iOS / Swift — Back4app Swift SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
var book = Book()
book.title = "Dune"
book.author = try author.toPointer() // Pointer — typed one-to-many edge
let saved = try await book.save()
let relation = try saved.relation("genres")
try await relation.add([sciFi, classics]).save() // Relation — many-to-many // Android / Kotlin — Back4app Android SDK
// One-to-many: a Pointer. Many-to-many: a Relation.
val book = ParseObject("Book").apply {
put("title", "Dune")
put("author", author) // Pointer — typed one-to-many edge
}
book.save()
val genres = book.getRelation<ParseObject>("genres") // Relation — many-to-many
genres.add(sciFi)
genres.add(classics)
book.save() Conceptuel vs. logique vs. physique : les trois niveaux
| Dimension | Conceptuel | Logique | Physique |
|---|---|---|---|
| Question traitée | Ce qui existe, comment c’est relié | Quels champs, quelles clés | Comment c’est stocké, à quelle vitesse |
| Public | Tout le monde | Concepteurs | Ingénieurs + le moteur |
| Contient | Entités, relations | + attributs, types, cardinalité | + index, contraintes, partitions |
| Change quand | Le métier change | Les exigences s’affinent | Le moteur ou l’échelle change |
La discipline qu’imposent les niveaux : ne débattez pas des index tant que l’équipe n’est pas d’accord sur ce qu’est une “commande”.
Chaque relation, chaque implémentation
La table que les résultats de recherche n’ont jamais construite — chaque type d’arête avec son implémentation dans les deux mondes :
| Relation | Exemple | Implémentation relationnelle | Implémentation documentaire |
|---|---|---|---|
| Un-à-un | Utilisateur ↔ profil | FK avec UNIQUE, ou même ligne | Embarquez — presque toujours |
| Un-à-quelques | Personne → adresses | Table enfant + FK | Tableau embarqué (borné) |
| Un-à-plusieurs | Auteur → livres | FK du côté “plusieurs” | Pointer du côté “plusieurs” |
| Un-à-énormément | Appareil → événements | FK + partitionnement | Pointer sur l’enfant ; jamais un tableau |
| Plusieurs-à-plusieurs | Livres ↔ genres | Table de jointure, PK composite | Relation ou tableaux de pointers |
| Autoréférence | Employé → manager | FK vers sa propre table | Pointer vers sa propre classe |
La notation de cardinalité, pour lire les diagrammes : la patte d’oie (crow’s foot) dessine une barre pour “un” et une fourche à trois branches pour “plusieurs” ; la tradition entité-association écrit 1 et N sur les lignes ; UML écrit des multiplicités comme 1 et *. Trois dialectes, une seule grammaire.
Normaliser, dénormaliser ou embarquer ?
La modélisation relationnelle part de la normalisation — découper les données pour que chaque fait n’existe qu’une fois, ce qui protège les écritures des anomalies. La modélisation analytique et documentaire la plie délibérément : la dénormalisation duplique les champs très lus pour supprimer des jointures, et l’embarquement est le cousin documentaire de la dénormalisation. La checklist embarquer vs. référencer se résume à trois questions : lus ensemble ? possédés par un seul parent ? de taille bornée ? Trois oui, on embarque ; un seul non, on référence. Et par-dessus tout, la règle moderne que les guides généralistes passent sous silence : listez d’abord les requêtes. Un modèle est correct quand les patterns d’accès qu’il doit servir sont peu coûteux — les entités seules ne peuvent pas vous le dire.
Cas d’usage courants
- Concevoir un nouveau backend. Le passage classique : nommer les entités, tracer les arêtes, choisir les implémentations d’après la table ci-dessus — avant la première ligne de code.
- La table de jointure avec attributs. Inscriptions, adhésions, lignes de commande — quand l’arête elle-même porte des données (date, quantité, rôle), la table de jointure (ou une classe d’arête avec deux pointers) devient une entité à part entière.
- Démêler un schéma qui a grandi. Les symptômes renvoient aux arêtes : des lignes dupliquées révèlent un plusieurs-à-plusieurs mal modélisé ; des documents obèses révèlent un embarquement non borné.
- Migrer d’un monde à l’autre. Passer du relationnel au documentaire, c’est trancher à nouveau, pour chaque FK, entre embarquement et pointer ; la table ci-dessus sert de dictionnaire de traduction.
- Alimenter l’IA et l’analytique. Les entrepôts de données veulent des arêtes explicites et stables — la dette de modélisation refait surface le jour où vous tentez un export.
Comment modéliser chaque arête ? Matrice de décision
| Choisissez… | Quand… | Attention à… |
|---|---|---|
| Embarquer | Lu ensemble, possédé, borné | La croissance : les “quelques” d’aujourd’hui sont les milliers de demain |
| Pointer / FK | Cycle de vie indépendant, forte cardinalité | Indexez-le — chaque lookup et chaque include en paie le prix |
| Relation / table de jointure | Plusieurs-à-plusieurs, ou l’arête porte des données | Le sens de la requête : sachez de quel côté vous interrogerez |
| Dupliquer (dénormaliser) | Un champ très lu qui traverse une arête | Le fan-out des mises à jour — la duplication est une dette avec intérêts |
Limites et trade-offs
- Les modèles figent des hypothèses. Les décisions de cardinalité (“un utilisateur a une adresse”) deviennent du schéma ; peu coûteuses à changer sur le papier, chères après le lancement — modélisez pour la cardinalité de demain.
- Les deux mondes punissent l’arête non indexée. Colonnes FK et champs pointer sont des chemins de jointure ; oublier leurs index est le bug de performance silencieux le plus courant.
- L’embarquement échange l’intégrité contre la localité. Aucun moteur ne garantit qu’une copie embarquée reste cohérente avec sa source — c’est désormais le rôle de votre logique de mise à jour.
- Les tables de jointure multiplient les jointures ; les relations les masquent. Chaque lecture plusieurs-à-plusieurs traverse le stockage des arêtes — budgétez le chemin de requête, quel que soit votre monde.
- Modéliser par patterns d’accès a aussi un coût. Optimiser pour les requêtes d’aujourd’hui peut marier le schéma au produit d’aujourd’hui ; gardez le modèle conceptuel comme vérité de référence neutre.
La modélisation de données sur Back4app
Back4app est une plateforme open-source de Backend as a Service (BaaS) qui combine une base de données gérée, des API REST et GraphQL générées automatiquement, l’authentification, le stockage de fichiers et des fonctions serverless avec Cloud Code. Son vocabulaire de modélisation, c’est la colonne documentaire des tables ci-dessus, promue au premier rang : les Pointers sont des arêtes un-à-plusieurs typées, les Relations portent le plusieurs-à-plusieurs sans table de jointure bricolée à la main, et les tableaux couvrent les petits ensembles bornés. Chaque arête que vous déclarez est immédiatement parcourable — include() suit les pointers en une seule requête, GraphQL imbrique les relations en une seule requête — et le schéma reste visible et modifiable dans le dashboard, si bien que le modèle physique ne sort jamais du champ de vision de l’équipe qui a conçu le modèle conceptuel.
Questions fréquentes
Qu'est-ce que la modélisation de données ?
Le processus qui consiste à traduire l'information d'une application — ses entités, leurs attributs et les relations entre elles — en une conception qu'une base de données peut stocker. Elle passe généralement par trois niveaux de détail : un modèle conceptuel qui nomme les entités, un modèle logique qui ajoute attributs et clés, et un modèle physique qui s'engage sur des tables, des colonnes et des index dans un moteur précis.
Quels sont les trois types de modèles de données ?
Conceptuel, logique et physique — la même conception à un niveau de zoom croissant. Le conceptuel répond à "qu'est-ce qui existe et comment cela se relie" pour les interlocuteurs métier. Le logique ajoute attributs, types et clés tout en restant indépendant de la technologie. Le physique s'engage sur un moteur réel : tables ou collections, index, contraintes. Chaque niveau est le précédent, plus des décisions.
Qu'est-ce qu'une relation un-à-plusieurs ?
Un enregistrement parent relié à plusieurs enfants, chaque enfant appartenant à exactement un parent — un client et ses commandes, un auteur et ses livres. C'est la relation la plus courante dans n'importe quel schéma. Les bases relationnelles l'implémentent avec une clé étrangère du côté "plusieurs" ; les bases documentaires utilisent un tableau embarqué pour les petits ensembles bornés, ou un pointer vers le parent pour tout le reste.
Qu'est-ce qu'une relation plusieurs-à-plusieurs et pourquoi exige-t-elle une table de jointure ?
Chaque côté est relié à plusieurs éléments de l'autre — étudiants et cours, livres et genres. Une colonne de clé étrangère ne peut pointer que vers une seule ligne ; les bases relationnelles décomposent donc le plusieurs-à-plusieurs en deux relations un-à-plusieurs via une table de jointure qui contient les deux clés (et souvent des attributs de la relation, comme une date d'inscription). Les bases documentaires se passent de la table de jointure : des tableaux de références, ou un type relation dédié, portent l'arête directement.
Comment distinguer un-à-plusieurs et plusieurs-à-plusieurs ?
Posez la question d'appartenance dans les deux sens. "Un auteur peut-il avoir plusieurs livres ?" Oui. "Un livre peut-il avoir plusieurs auteurs ?" Si non — un-à-plusieurs, clé étrangère sur le livre. Si oui — plusieurs-à-plusieurs, table de jointure ou relation. Se tromper ici est l'erreur de modélisation classique : un plusieurs-à-plusieurs modélisé en un-à-plusieurs duplique des lignes ou perd des arêtes en silence.
Qu'est-ce que la cardinalité dans un diagramme entité-association ?
Le nombre d'instances d'une entité qui peuvent être reliées aux instances d'une autre — un-à-un, un-à-plusieurs, plusieurs-à-plusieurs. Les diagrammes l'expriment dans l'une de trois notations : des chiffres et des lettres sur les lignes de liaison, les symboles en patte d'oie (crow's foot) — une barre pour un, une fourche à trois branches pour plusieurs — ou des plages de multiplicité comme 1 et astérisque. Même sémantique, conventions de dessin différentes.
Comment les bases documentaires modélisent-elles les relations sans clés étrangères ?
Avec trois outils : l'embarquement (imbriquer les données liées dans le document parent — adapté quand elles sont lues ensemble, possédées par un seul parent et bornées), les pointers ou références (stocker l'ID du document lié dans un champ typé — adapté aux cycles de vie indépendants et à la forte cardinalité), et les objets relation ou tableaux d'ID pour le plusieurs-à-plusieurs. La règle directrice bascule de la normalisation vers les patterns d'accès : ce qui se lit ensemble doit vivre ensemble.
Quelles sont les erreurs de modélisation de données les plus courantes ?
Un top cinq stable : modéliser un plusieurs-à-plusieurs en un-à-plusieurs ; oublier les index sur les champs de clé étrangère et de pointer (chaque jointure et chaque lookup en paie le prix) ; des tableaux embarqués non bornés dans les schémas documentaires ; la dénormalisation prématurée, avant qu'aucune requête ne se soit révélée lente ; et modéliser à partir des seules entités sans lister les requêtes — les patterns d'accès — que le modèle doit servir.