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.
@Cœur de pierre
J'irais ici avec EAV et MVC jusqu'au bout.
@Bill Karvin
Toutes ces choses que vous avez mentionnées ici:
à mon avis, n'appartient pas du tout à une base de données car aucune des bases de données n'est capable de gérer ces interactions et ces exigences à un niveau approprié comme le fait un langage de programmation d'une application.
À mon avis, utiliser une base de données de cette manière, c'est comme utiliser une pierre pour enfoncer un clou. Vous pouvez le faire avec une pierre mais n'êtes-vous pas supposé utiliser un marteau plus précis et spécifiquement conçu pour ce genre d'activité?
Ce problème peut être résolu en effectuant quelques requêtes sur des données partielles et en les traitant sous forme de tableau avec votre application. Même si vous disposez de 600 Go de données produit, vous pouvez les traiter par lots si vous avez besoin des données de chaque ligne de ce tableau.
Aller plus loin Si vous souhaitez améliorer les performances des requêtes, vous pouvez sélectionner certaines opérations comme par exemple la création de rapports ou la recherche de texte globale et préparer pour elles des tables d'index qui stockeraient les données requises et seraient régénérées périodiquement, disons toutes les 30 minutes.
Vous n'avez même pas besoin de vous soucier du coût du stockage de données supplémentaire, car il devient chaque jour moins cher et moins cher.
Si vous êtes toujours préoccupé par les performances des opérations effectuées par l'application, vous pouvez toujours utiliser Erlang, C ++, Go Language pour pré-traiter les données et ensuite simplement traiter les données optimisées plus loin dans votre application principale.
la source
you can always use Erlang, C++, Go Language to pre-process the data
Que voulais-tu dire? Au lieu de DB, utilisez Go lang? Pourriez-vous nous en dire plus?Si j'utilise le
Class Table Inheritance
sens:Ce que j'aime le plus parmi les suggestions de Bill Karwin. Je peux prévoir un inconvénient, que je vais essayer d'expliquer comment éviter de devenir un problème.
Quel plan d'urgence dois-je mettre en place lorsqu'un attribut qui n'est commun qu'à 1 type, devient alors commun à 2, puis 3, etc.?
Par exemple: (ce n'est qu'un exemple, pas mon vrai problème)
Si nous vendons des meubles, nous pouvons vendre des chaises, des lampes, des canapés, des téléviseurs, etc. Je mettrais donc l'
power_consumption
attribut sur letv_type_table
. Mais ensuite, nous commençons à proposer des systèmes de cinéma maison qui ont également unepower_consumption
propriété. OK, c'est juste un autre produit, je vais donc ajouter ce champ à lastereo_type_table
car c'est probablement le plus facile à ce stade. Mais au fil du temps, alors que nous commençons à transporter de plus en plus d'électronique, nous nous rendons compte quepower_consumption
c'est assez large pour qu'il devrait être dans lemain_product_table
. Qu'est-ce que je devrais faire maintenant?Ajoutez le champ au
main_product_table
. Écrivez un script pour parcourir l'électronique et mettez la valeur correcte de chacuntype_table
dans lemain_product_table
. Supprimez ensuite cette colonne de chacuntype_table
.Maintenant, si j'utilisais toujours la même
GetProductData
classe pour interagir avec la base de données pour extraire les informations sur le produit; alors si des changements dans le code doivent maintenant être refactorisés, ils ne devraient concerner que cette classe.la source
Vous pouvez avoir une table Product et une table ProductAdditionInfo distincte avec 3 colonnes: ID de produit, nom d'informations supplémentaires, valeur d'informations supplémentaires. Si la couleur est utilisée par de nombreux types de produits, mais pas par tous, vous pouvez l'inclure dans une colonne Nullable dans la table Product ou simplement la placer dans ProductAdditionalInfo.
Cette approche n'est pas une technique traditionnelle pour une base de données relationnelle, mais je l'ai vu beaucoup utilisée dans la pratique. Il peut être flexible et avoir de bonnes performances.
Steve Yegge appelle cela le modèle Properties et a écrit un long article sur son utilisation.
la source
3 columns: product ID, additional info name, additional info value
j'ai compris le concept. Et j'ai déjà fait cela avant, et j'ai rencontré des problèmes. Cependant, je ne me souviens pas pour le moment quels étaient ces problèmes.