Base de données de valeurs d'attributs d'entité et commerce électronique de modèle relationnel strict

136

Il est prudent de dire que le modèle de base de données EAV / CR est mauvais. Cela dit,

Question: Quel modèle, technique ou modèle de base de données doit être utilisé pour traiter les «classes» d'attributs décrivant les produits de commerce électronique qui peuvent être modifiés au moment de l'exécution?

Dans une bonne base de données E-commerce, vous stockerez des classes d'options (comme la résolution TV, vous aurez alors une résolution pour chaque téléviseur, mais le produit suivant peut ne pas être un téléviseur et ne pas avoir de «résolution TV»). Comment les stocker, rechercher efficacement et permettre à vos utilisateurs de configurer des types de produits avec des champs variables décrivant leurs produits? Si le moteur de recherche constate que les clients recherchent généralement des téléviseurs en fonction de la profondeur de la console, vous pouvez ajouter une profondeur de console à vos champs, puis ajouter une seule profondeur pour chaque type de produit de télévision au moment de l'exécution.

Il existe une fonctionnalité commune intéressante parmi les bonnes applications de commerce électronique: elles affichent un ensemble de produits, puis des menus latéraux "d'exploration vers le bas" où vous pouvez voir "Résolution TV" comme en-tête, et les cinq résolutions TV les plus courantes pour le trouvé ensemble. Vous cliquez sur l'un d'entre eux et il n'affiche que les téléviseurs de cette résolution, ce qui vous permet d'approfondir davantage en sélectionnant d'autres catégories dans le menu latéral. Ces options seraient les attributs de produit dynamiques ajoutés au moment de l'exécution.

Discussion supplémentaire:

Bref, y a-t-il des liens sur Internet ou des descriptions de modèles qui pourraient «académiquement» corriger la configuration suivante? Je remercie Noel Kennedy d'avoir suggéré un tableau de catégories, mais le besoin peut être plus grand que cela. Je le décris d'une manière différente ci-dessous, en essayant de mettre en évidence la signification. J'ai peut-être besoin d'une correction de point de vue pour résoudre le problème, ou j'ai peut-être besoin d'aller plus loin dans l'EAV / CR.

J'adore la réponse positive au modèle EAV / CR. Mes collègues développeurs disent tous ce que Jeffrey Kemp a évoqué ci-dessous: "les nouvelles entités doivent être modélisées et conçues par un professionnel" (hors contexte, lire sa réponse ci-dessous). Le problème est:

  • les entités ajoutent et suppriment des attributs chaque semaine
    (les mots-clés de recherche dictent les attributs futurs)
  • de nouvelles entités arrivent chaque semaine
    (les produits sont assemblés à partir de pièces)
  • les anciennes entités disparaissent chaque semaine
    (archivées, moins populaires, saisonnières)

Le client souhaite ajouter des attributs aux produits pour deux raisons:

  • service / recherche par mot-clé / tableau de comparaison entre des produits similaires
  • configuration du produit de consommation avant le paiement

Les attributs doivent avoir une signification, pas seulement une recherche par mot-clé. S'ils veulent comparer tous les gâteaux qui ont un "glaçage à la crème fouettée", ils peuvent cliquer sur les gâteaux, cliquer sur le thème de l'anniversaire, cliquer sur le glaçage à la crème fouettée, puis vérifier tous les gâteaux qui sont intéressants sachant qu'ils ont tous un glaçage à la crème fouettée. Ce n'est pas spécifique aux gâteaux, juste un exemple.

Zachary Scott
la source
Pourquoi ne pouvez-vous pas simplement avoir une table de «catégorie» avec une clé étrangère se référant à elle-même?
Noel Kennedy
29
Il n'est ni sûr ni précis de dire que le modèle de base de données EAV est mauvais, car il est bien adapté à certaines applications.
spencer7593
Que faire si vous décorez divers objets avec diverses propriétés, héritant d'un parent comme dans Entity Framework 4? Comment persiste-t-il ces objets?
Zachary Scott
1
Je reviens juste à cet excellent article sur l'expérience d'un consultant avec un système basé sur une version extrême d'EAV. Lis le! simple-talk.com/opinion/opinion-pieces/bad-carma
Jeffrey Kemp
1
EAV est un modèle de base de données très viable. Je travaille sur un problème similaire comme vous et la solution est EAV. Je recommanderais l'article suivant: sqlblog.com/blogs/aaron_bertrand/archive/2009/11/19/…
Sandor

Réponses:

75

Il y a quelques avantages et inconvénients généraux auxquels je peux penser, il y a des situations où l'un est meilleur que l'autre:

Option 1, modèle EAV:

  • Pro: moins de temps pour concevoir et développer une application simple
  • Pro: de nouvelles entités faciles à ajouter (pourraient même être ajoutées par les utilisateurs?)
  • Pro: composants d'interface "génériques"
  • Contre: code complexe requis pour valider des types de données simples
  • Contre: SQL beaucoup plus complexe pour des rapports simples
  • Contre: les rapports complexes peuvent devenir presque impossibles
  • Inconvénient: performances médiocres pour les grands ensembles de données

Option 2, modéliser chaque entité séparément:

  • Inconvénient: plus de temps requis pour rassembler les exigences et la conception
  • Contre: les nouvelles entités doivent être modélisées et conçues par un professionnel
  • Con: composants d'interface personnalisés pour chaque entité
  • Pro: contraintes de type de données et validation simples à mettre en œuvre
  • Pro: SQL est facile à écrire, à comprendre et à déboguer
  • Pro: même les rapports les plus complexes sont relativement simples
  • Pro: meilleures performances pour les grands ensembles de données

Option 3, combinaison (modèle d'entités "correctement", mais ajoutez des "extensions" pour les attributs personnalisés pour certaines / toutes les entités)

  • Avantages / inconvénients: plus de temps requis pour rassembler les exigences et la conception que l'option 1, mais peut-être pas autant que l'option 2 *
  • Contre: les nouvelles entités doivent être modélisées et conçues par un professionnel
  • Pro: de nouveaux attributs pourraient être facilement ajoutés plus tard
  • Contre: code complexe requis pour valider des types de données simples (pour les attributs personnalisés)
  • Inconvénient: des composants d'interface personnalisés sont toujours nécessaires, mais des composants d'interface génériques peuvent être possibles pour les attributs personnalisés
  • Con: SQL devient complexe dès qu'un attribut personnalisé est inclus dans un rapport
  • Inconvénient: bonnes performances en général, à moins que vous n'ayez besoin de rechercher ou de signaler par les attributs personnalisés

* Je ne sais pas si l'option 3 permettrait nécessairement de gagner du temps dans la phase de conception.

Personnellement, je pencherais vers l'option 2 et éviterais EAV dans la mesure du possible. Cependant, pour certains scénarios, les utilisateurs ont besoin de la flexibilité fournie avec EAV; mais cela a un coût élevé.

Jeffrey Kemp
la source
Et si vous aviez une seule table avec des index pour les valeurs de texte 1-n, alors en C # (en RAM) mappez ce que vous voulez à ce dont vous avez besoin. Cela fonctionnerait toujours comme un EAV, mais les «correspondances» seraient des modèles de domaine. Un peu comme une sérialisation, mais vous pouvez utiliser des sélections SQL sur des champs de texte indexés. Pas de sélections multiples par enregistrement. Tout le «coût» se produit dans la RAM.
Zachary Scott
1
@Zim, cela ressemble à peu près à l'option 3. Chaque ligne a 1-n colonnes "génériques" supplémentaires, et les données qui y sont stockées sont interprétées au niveau de l'application. Vous bénéficiez de l'avantage de disposer de toutes les données d'un enregistrement en un seul endroit. Les métadonnées sur ces colonnes doivent être stockées quelque part, cependant, et c'est là que le coût s'infiltre. Bien sûr, nous pouvons mettre en cache les métadonnées dans la mémoire vive, mais cela coûte toujours plus que d'avoir le domaine modélisé directement dans le code d'application. Certainement mieux qu'un modèle EAV à part entière!
Jeffrey Kemp
1
+10000 Excellente réponse. De nos jours, les gens lésinent sur la conception de bases de données et la collecte des exigences. Ils préfèrent écrire cent fois plus de lignes de code, qui prennent le temps de faire un bon design.
Tulains Córdova
Vous n'avez pas besoin de plus de conception pour l'option relationnelle (2) que l'option EAV (1) si vous ne fournissez que la structure de l'option 1. Et l'interface relationnelle est générique à partir des métadonnées décrivant cette structure. Cela supprime toute l'option 2 Cons. Cependant, vous avez oublié le seul vrai Con: DDL peut être trop lent à gérer les tables.
philipxy
Salut @philipxy, je n'ai pas dit "plus de design". La raison d'être de l'EAV est que (vraisemblablement) le concepteur du système peut passer moins de temps sur la conception du modèle, laissant ce travail de conception aux «utilisateurs» plus tard (ce manque de conception professionnelle conduit aux inconvénients répertoriés pour l'option 1) . Si l'EAV n'entraîne aucune économie pour le concepteur, cela ne fait qu'ajouter plus de carburant au feu pour rejeter l'EAV d'emblée. De plus, je ne suis pas d'accord pour dire que DDL est "trop ​​lent" - puisqu'il ne devrait être requis que rarement (c'est-à-dire pour corriger les erreurs dans le modèle ou pour implémenter de nouvelles fonctionnalités), ses performances devraient être relativement peu importantes.
Jeffrey Kemp
63

Il est prudent de dire que le modèle de base de données EAV / CR est mauvais.

Non ce n'est pas. C'est juste qu'il s'agit d'une utilisation inefficace des bases de données relationnelles. Un magasin purement clé / valeur fonctionne très bien avec ce modèle.

Maintenant, à votre vraie question: comment stocker divers attributs et les garder consultables?

Utilisez simplement EAV. Dans votre cas, ce serait une seule table supplémentaire. indexez-le à la fois sur le nom et la valeur de l'attribut, la plupart des RDBM utiliseraient la compression de préfixe sur les répétitions de nom d'attribut, ce qui le rendrait vraiment rapide et compact.

EAV / CR devient moche lorsque vous l'utilisez pour remplacer des champs «réels». Comme pour tout outil, en abuser est «mauvais» et lui donne une mauvaise image.

Javier
la source
donc la question est que j'ai 15 champs supplémentaires pour l'une de mes catégories et dans le modèle eav, il faut 16 jointures + table principale, donc faire 16 jointures de gauche pour rechercher des produits (et avoir 16 où si le client le souhaite) dans 3-4 millions d'enregistrements ( un site Web de vente de produits d'occasion par des particuliers), donc les performances sont-elles faibles?
babak faghihian
2
Si ces "champs supplémentaires" sont déjà définis, alors il vaut mieux le faire en tant que "champs réels". Et bien sûr, faire un nombre illimité de jointures dans une requête volumineuse serait un lourd tribut (mais cela pourrait toujours être correct!). Ce que j'ai fait sur un projet lourd de métadonnées, c'est d'autoriser n'importe quel nombre de "balises" (en tant qu'enregistrements EAV) par "élément principal", mais la "grande requête" ne sélectionne que quelques tagnames prédéfinis, en limitant le nombre total de jointures (typique est actuellement seulement 4 balises et environ 5 autres jointures), et lorsque l'utilisateur sélectionne un élément de spécifique, puis il fetchs tout ce qui concerne, mais pour un seul élément.
Javier
mais bien sûr, ce système spécifique est actuellement porté sur un hstorechamp (juste une des raisons pour lesquelles nous utilisons PostgreSQL)
Javier
15
// À ce stade, j'aimerais prendre un moment pour vous parler du format Magento / Adobe PSD .
// Magento / PSD n'est pas une bonne plate-forme / format de commerce électronique . Magento / PSD n'est même pas une mauvaise plate-forme / format de commerce électronique . L'appeler tel serait un
// insulte à d'autres mauvaises plates-formes / formats de commerce électronique , tels que Zencart ou OsCommerce. Non, Magento / PSD est une plate-forme / format de commerce électronique épouvantable . Ayant
// a travaillé sur ce code pendant plusieurs semaines maintenant, ma haine pour Magento / PSD est devenue un feu qui fait rage
// qui brûle avec la passion féroce d'un million de soleils.

http://code.google.com/p/xee/source/browse/trunk/XeePhotoshopLoader.m?spec=svn28&r=11#107

Les modèles internes sont au mieux farfelus, comme quelqu'un qui a mis le schéma dans un jeu de boggle, l'a scellé et l'a mis dans un shacker de peinture ...

Monde réel: je travaille sur une application d'exécution de midware et voici l'une des requêtes pour obtenir des informations d'adresse.

CREATE OR REPLACE VIEW sales_flat_addresses AS
SELECT sales_order_entity.parent_id AS order_id, 
       sales_order_entity.entity_id, 
       CONCAT(CONCAT(UCASE(MID(sales_order_entity_varchar.value,1,1)),MID(sales_order_entity_varchar.value,2)), "Address") as type, 
       GROUP_CONCAT( 
         CONCAT( eav_attribute.attribute_code," ::::: ", sales_order_entity_varchar.value )
         ORDER BY sales_order_entity_varchar.value DESC
         SEPARATOR '!!!!!' 
       ) as data
  FROM sales_order_entity
       INNER JOIN sales_order_entity_varchar ON sales_order_entity_varchar.entity_id = sales_order_entity.entity_id
       INNER JOIN eav_attribute ON eav_attribute.attribute_id = sales_order_entity_varchar.attribute_id
   AND sales_order_entity.entity_type_id =12
 GROUP BY sales_order_entity.entity_id
 ORDER BY eav_attribute.attribute_code = 'address_type'

Exige des informations d'adresse pour une commande, paresseusement

-

Résumé: n'utilisez Magento que si:

  1. On vous donne de gros sacs d'argent
  2. Vous devez
  3. Profitez de la douleur
Vee
la source
Ceci est un article plus ancien mais j'aurais aimé l'avoir trouvé il y a 3 mois lorsque j'ai commencé un projet Magento pour un client. +1 pour l'analogie boggle / paint-shaker!
trevorc
1
Assez intéressant, magento semble être le roi de la route en termes de systèmes de commerce électronique. Peut-être que c'est seulement le marketing est très bon
Herr
1
Magento n'est pas populaire en raison du niveau de maintenance, mais de la possibilité de personnaliser, permettant à quiconque d'implémenter de nouvelles fonctionnalités sans changement d'architecture ou peu de modifications. Cette fonctionnalité a un coût.
Diego Mendes
Éloignez-vous de Magento 2 si vous voulez éviter Triple Pain and More Pain en plus pour FE et BE
TheBlackBenzKid
15

Je suis surpris que personne n'ait mentionné les bases de données NoSQL.

Je n'ai jamais pratiqué NoSQL dans un contexte de production (je viens de tester MongoDB et j'ai été impressionné) mais le but de NoSQL est de pouvoir enregistrer des éléments avec des attributs différents dans le même «document».

Lucas T
la source
Considérez que les écritures sur MongoDB nécessitent un verrouillage au niveau de la base de données , et ce que cela signifie pour le trafic de production simultané.
Bill Karwin
Considérez que la durée du verrouillage est de l'ordre de quelques microsecondes.
Hello World
12

Lorsque les performances ne sont pas une exigence majeure, comme dans une application de type ETL, EAV a un autre avantage distinct: les sauvegardes différentielles.

J'ai implémenté un certain nombre d'applications où une exigence primordiale était la possibilité de voir l'historique d'un objet de domaine depuis sa première «version» jusqu'à son état actuel. Si cet objet de domaine a un grand nombre d'attributs, cela signifie que chaque modification nécessite qu'une nouvelle ligne soit insérée dans sa table correspondante (pas une mise à jour car l'historique serait perdu, mais une insertion). Disons que cet objet de domaine est une personne et que j'ai 500 000 personnes à suivre avec une moyenne de plus de 100 changements au cours du cycle de vie des personnes pour divers attributs. Ajoutez à cela le fait que l'application ne possède qu'un seul objet de domaine majeur est rare et vous supposerez rapidement que la taille de la base de données deviendrait rapidement incontrôlable.

Une solution simple consiste à enregistrer uniquement les modifications différentielles des principaux objets du domaine plutôt que d'enregistrer à plusieurs reprises les informations redondantes.

Tous les modèles changent au fil du temps pour refléter les nouveaux besoins commerciaux. Période. L'utilisation d'EAV n'est que l'un des outils de notre boîte à utiliser; mais il ne devrait jamais être automatiquement classé comme «mauvais».

Jerry Jasperson
la source
2
+1 pour "Utiliser EAV n'est qu'un des outils de notre boîte à utiliser; mais il ne devrait jamais être automatiquement classé comme" mauvais "."
Catchops le
Btw, cela s'appelle SCD (dimensions changeantes lentement). Les exigences bitemporelles (un cas spécifique du SCD de type 4) appellent également un schéma EAV pour les attributs qui ont cette propriété. N'oubliez pas que 99% de NoSQL n'a pas de jointures natives, donc si vous avez besoin de jointures «en direct» avec ce type de données, EAV est la seule solution.
cowbert
3

Je lutte avec le même problème. Il peut être intéressant pour vous de consulter la discussion suivante sur deux solutions de commerce électronique existantes: Magento (EAV) et Joomla (structure relationnelle régulière): https://forum.virtuemart.net/index.php?topic=58686.0

Il semble que la performance EAV de Magento soit un véritable coup de cœur.

C'est pourquoi je penche vers une structure normalisée. Pour surmonter le manque de flexibilité, je pense ajouter à l'avenir un dictionnaire de données séparé (XML ou tables DB séparées) qui pourrait être édité, et sur cette base, le code d'application pour afficher et comparer les catégories de produits avec un nouvel ensemble d'attributs serait généré, ainsi que des scripts SQL.

Une telle architecture semble être le bonbon dans ce cas - flexible et performante à la fois.

Le problème pourrait être l'utilisation fréquente d'ALTER TABLE dans un environnement réel. J'utilise Postgres, donc son MVCC et son DDL transactionnel soulageront, espérons-le, la douleur.

aaimnr
la source
2

Je vote toujours pour la modélisation au niveau atomique le plus bas significatif pour EAV. Laissez les normes, les technologies et les applications orientées vers certaines communautés d'utilisateurs décider des modèles de contenu, des besoins de répétition des attributs, des grains, etc.

Amanda Xu
la source
2

S'il ne s'agit que des attributs du catalogue de produits et que, par conséquent, les exigences de validation pour ces attributs sont plutôt limitées, le seul inconvénient réel de l'EAV est la performance des requêtes et même cela n'est qu'un problème lorsque votre requête traite de plusieurs «choses» (produits) avec des attributs, les performances pour la requête "donnez-moi tous les attributs pour le produit avec l'ID 234", alors qu'elles ne sont pas optimales, sont toujours très rapides.

Une solution consiste à utiliser le modèle de base de données SQL / EAV uniquement pour le côté administrateur / édition du catalogue de produits et de disposer d'un processus qui dénormalise les produits en quelque chose qui permet de les rechercher. Puisque vous avez déjà des attributs et qu'il est donc plutôt probable que vous vouliez des facettes, ce quelque chose pourrait être Solr ou ElasticSearch. Cette approche évite essentiellement tous les inconvénients du modèle EAV et la complexité supplémentaire est limitée à la sérialisation d'un produit complet vers JSON lors de la mise à jour.

bob
la source
2

L'EAV présente de nombreux inconvénients:

  1. Dégradation des performances au fil du temps Une fois que la quantité de données dans l'application dépasse une certaine taille, la récupération et la manipulation de ces données sont susceptibles de devenir de moins en moins efficaces.
  2. Les requêtes SQL sont très complexes et difficiles à écrire.
  3. Problèmes d'intégrité des données. Vous ne pouvez pas définir de clés étrangères pour tous les champs nécessaires.
  4. Vous devez définir et gérer vos propres métadonnées.
Gabriel Voinea
la source
1. Ceci est également vrai pour la plupart des bases de données relationnelles; c'est pourquoi le sharding a été inventé. 2. La modélisation des données peut être complexe et difficile à mettre en œuvre. J'ai passé des semaines et des mois à attendre les changements de schéma de cube OLAP. 3. Déjà principalement fait dans le logiciel maintenant 4. Vous devez le faire "dans ERwin, Excel et Visio" lors de la modélisation d'un schéma relationnel de toute façon.
cowbert
1

J'ai un problème légèrement différent: au lieu de nombreux attributs avec des valeurs éparses (ce qui est peut-être une bonne raison d'utiliser EAV), je souhaite stocker quelque chose qui ressemble plus à une feuille de calcul. Les colonnes de la feuille peuvent changer, mais dans une feuille, toutes les cellules contiendront des données (pas éparses).

J'ai fait une petite série de tests pour comparer deux conceptions: l'une utilisant EAV et l'autre utilisant un Postgres ARRAY pour stocker les données de cellule.

EAV entrez la description de l'image ici

Tableau entrez la description de l'image ici

Les deux schémas ont des index sur les colonnes appropriées et les index sont utilisés par le planificateur.

Il s'est avéré que le schéma basé sur un tableau était un ordre de grandeur plus rapide pour les insertions et les requêtes. À partir de tests rapides, il semble que les deux évoluent de manière linéaire. Les tests ne sont cependant pas très approfondis. Les suggestions et les fourchettes sont les bienvenues - elles sont sous une licence MIT.

z0r
la source
comment avez-vous fait des jointures sur les colonnes de la feuille (c'est-à-dire vlookup) avec le modèle de tableau? N'avez-vous pas à écrire votre propre fonction de tri par fusion de tableaux? Je doute fort qu'il puisse être aussi bon que le tri de fusion précompilé si vous avez utilisé sheet_id + coordonnée x + coordonnée y d'une cellule comme clé de la valeur de la cellule. (pour émuler Excel, prégénérer une table de recherche pour les coordonnées x où 0-18278 sont des colonnes A-ZZZ (excel maxes out à 16384)), vous pouvez alors sélectionner des valeurs où sheet_id = uuid et x-coord = 0 et y-coord <1001 pour obtenir les 1000 premiers rangs du col A.
cowbert
@cowbert vous avez raison; en fait, je charge juste les colonnes qui m'intéressent et je fais la jointure en Python. Mou!
z0r