Vous disposez d'au moins ces cinq options pour modéliser la hiérarchie de types que vous décrivez:
Héritage de table unique : une table pour tous les types de produits, avec suffisamment de colonnes pour stocker tous les attributs de tous les types. Cela signifie beaucoup de colonnes, dont la plupart sont NULL sur une ligne donnée.
Héritage de table de classe : une table pour les produits, stockant les attributs communs à tous les types de produits. Puis une table par type de produit, stockant les attributs spécifiques à ce type de produit.
Héritage de table en béton : pas de tableau pour les attributs produits communs. Au lieu de cela, une table par type de produit, stockant à la fois les attributs de produit communs et les attributs spécifiques au produit.
LOB sérialisé : une table pour les produits, stockant les attributs communs à tous les types de produits. Une colonne supplémentaire stocke un BLOB de données semi-structurées, au format XML, YAML, JSON ou dans un autre format. Ce BLOB vous permet de stocker les attributs spécifiques à chaque type de produit. Vous pouvez utiliser des modèles de conception sophistiqués pour décrire cela, tels que Façade et Memento. Mais quoi qu'il en soit, vous avez un tas d'attributs qui ne peuvent pas être facilement interrogés dans SQL; vous devez récupérer le blob entier dans l'application et le trier là-bas.
Entity-Attribute-Value : une table pour les produits et une table qui fait pivoter les attributs vers des lignes, au lieu de colonnes. EAV n'est pas une conception valide par rapport au paradigme relationnel, mais de nombreuses personnes l'utilisent quand même. C'est le "modèle de propriétés" mentionné par une autre réponse. Voir les autres questions avec la balise eav sur StackOverflow pour certains des pièges.
J'ai écrit plus à ce sujet dans une présentation, Modélisation extensible des données .
Réflexions supplémentaires sur l'EAV: Bien que de nombreuses personnes semblent favoriser l'EAV, je ne le suis pas. Cela semble être la solution la plus flexible, et donc la meilleure. Cependant, gardez à l'esprit l'adage TANSTAAFL . Voici quelques-uns des inconvénients de l'EAV:
- Pas moyen de rendre une colonne obligatoire (équivalent de
NOT NULL
).
- Aucun moyen d'utiliser les types de données SQL pour valider les entrées.
- Aucun moyen de garantir que les noms d'attributs sont orthographiés de manière cohérente.
- Aucun moyen de mettre une clé étrangère sur les valeurs d'un attribut donné, par exemple pour une table de recherche.
- La récupération des résultats dans une mise en page tabulaire conventionnelle est complexe et coûteuse, car pour obtenir des attributs à partir de plusieurs lignes, vous devez le faire
JOIN
pour chaque attribut.
Le degré de flexibilité que vous offre EAV nécessite des sacrifices dans d'autres domaines, rendant probablement votre code aussi complexe (ou pire) qu'il ne l'aurait été pour résoudre le problème d'origine d'une manière plus conventionnelle.
Et dans la plupart des cas, il n'est pas nécessaire d'avoir ce degré de flexibilité. Dans la question du PO sur les types de produits, il est beaucoup plus simple de créer un tableau par type de produit pour les attributs spécifiques au produit, de sorte que vous ayez une structure cohérente appliquée au moins pour les entrées du même type de produit.
J'utiliserais EAV uniquement si chaque ligne doit être autorisée à avoir potentiellement un ensemble distinct d'attributs. Lorsque vous avez un ensemble fini de types de produits, EAV est exagéré. L'héritage de table de classe serait mon premier choix.
Mise à jour 2019: plus je vois des gens utiliser JSON comme solution au problème des «nombreux attributs personnalisés», moins j'aime cette solution. Cela rend les requêtes trop complexes, même lorsque vous utilisez des fonctions JSON spéciales pour les prendre en charge. Le stockage des documents JSON nécessite beaucoup plus d'espace de stockage que le stockage dans des lignes et des colonnes normales.
Fondamentalement, aucune de ces solutions n'est simple ou efficace dans une base de données relationnelle. L'idée même d'avoir des «attributs variables» est fondamentalement en contradiction avec la théorie relationnelle.
En résumé, vous devez choisir l'une des solutions en fonction de celle qui est la moins mauvaise pour votre application. Par conséquent, vous devez savoir comment vous allez interroger les données avant de choisir une conception de base de données. Il n'y a aucun moyen de choisir une solution qui soit «meilleure» car l'une des solutions peut être la meilleure pour une application donnée.