Je pense utiliser un modèle EAV (entité-attribut-valeur) pour certains éléments de l'un des projets, mais toutes les questions à ce sujet dans Stack Overflow aboutissent à des réponses appelant EAV un anti-modèle.
Mais je me demande si c'est ce qui ne va pas dans tous les cas.
Supposons qu'une entité de produit de magasin ait des caractéristiques communes, telles que nom, description, image et prix, qui participent à la logique de nombreux lieux et présente des caractéristiques (semi) uniques, telles que la montre et le ballon de plage, qui seraient décrites sous des aspects complètement différents. Je pense donc que EAV conviendrait pour stocker ces caractéristiques (semi) uniques.
Tout cela suppose que, pour afficher la liste des produits, il suffit d’informations dans le tableau des produits (c’est-à-dire qu’il n’ya pas de fichier EAV) et juste lorsqu’un produit est présenté / comparé à 5 produits / etc. les données enregistrées avec EAV sont utilisées.
J'ai vu une telle approche dans le commerce Magento et elle est très populaire, y a-t-il des cas où EAV est raisonnable?
Réponses:
https://web.archive.org/web/20140831134758/http://www.dbforums.com/database-concepts-design/1619660-otlt-eav-design-why-do-people-hate.html
EAV permet au développeur de définir le schéma selon ses besoins, ce qui est utile dans certaines circonstances.
D'autre part, il fonctionne très mal dans le cas d'une requête mal définie et peut supporter d'autres mauvaises pratiques.
En d'autres termes, EAV vous donne assez de corde pour vous pendre et dans cette industrie, les choses devraient être conçues au plus bas niveau de complexité, car le type qui vous remplacera sur le projet sera probablement un idiot.
la source
En un mot, EAV est utile lorsque votre liste d'attributs s'allonge fréquemment ou qu'elle est si grande que la plupart des lignes sont remplies avec surtout des valeurs NULL si vous faites de chaque attribut une colonne. Il devient un anti-modèle lorsqu'il est utilisé en dehors de ce contexte.
la source
CREATE TABLE
pour le nouvel attribut?L'utilisation d'une structure EAV a plusieurs implications qui sont des compromis.
Vous négociez "moins d'espace pour la ligne, car vous ne disposez pas de 100 colonnes
null
" contre "des requêtes et un modèle plus complexes".Avoir un EAV signifie généralement que la valeur est une chaîne dans laquelle on peut rentrer toutes les données. Ceci a alors des implications sur la vérification de la validité et des contraintes. Considérez le cas où vous avez mis le nombre de piles utilisées dans le tableau EAV. Vous voulez trouver une lampe de poche utilisant des piles de taille C, mais moins de 4 d'entre elles.
La chose à réaliser ici est que vous ne pouvez pas utiliser un index de manière raisonnable sur la valeur. Vous ne pouvez pas non plus empêcher quelqu'un d'introduire quelque chose qui n'est pas un entier ou un entier non valide (utilise des piles '-1') car la colonne de valeurs est utilisée encore et encore à des fins différentes.
Cela a alors des implications pour essayer d’écrire un modèle pour le produit. Vous aurez les bonnes valeurs dactylographiées ... mais vous allez également avoir une
Map<String,String>
assise juste avec toutes sortes de choses dedans. Cela a alors des implications supplémentaires lors de la sérialisation en XML ou Json et de la complexité d'essayer de valider ou d'interroger ces structures.Certaines alternatives ou modifications du modèle à prendre en compte consistent, au lieu d'une clé de forme libre, à avoir une autre table avec des clés valides. Cela signifie qu'au lieu de faire des comparaisons de chaînes dans la base de données, vous vérifiez par rapport à l'égalité des identifiants de clé étrangère. Changer la clé elle-même se fait en un seul endroit. Vous avez un jeu de clés connu, ce qui signifie qu'elles peuvent être effectuées en tant qu'énum.
Vous pouvez également disposer de tables associées contenant les attributs d'une classe de produit spécifique. Un département d'épicerie peut avoir une autre table qui a plusieurs attributs associés dont les matériaux de construction n'ont pas besoin (et vice versa).
Il y a des moments qui appellent particulièrement une table EAV.
Pensez à la situation dans laquelle vous n'êtes pas simplement en train d'écrire un système d'inventaire pour votre entreprise dans lequel vous connaissez chaque produit et chaque attribut. Vous écrivez maintenant un système d'inventaire à vendre à d'autres entreprises. Vous ne pouvez pas connaître tous les attributs de chaque produit - ils devront les définir.
Une idée qui en ressort est "nous laisserons le client modifier la table" et c'est tout simplement mauvais (vous entrez dans la méta-programmation pour les structures de table parce que vous ne savez plus où se trouve, elles peuvent corrompre royalement ou corrompre l'application, ils ont le droit de faire de mauvaises choses et les implications de cet accès deviennent importantes). Il existe plus d'informations sur ce chemin sur MVC4: Comment créer un modèle au moment de l'exécution?
Au lieu de cela, vous créez l'interface administrative dans une table EAV et autorisez son utilisation. Si le client veut créer une entrée pour 'polkadots', il va dans la table EAV et vous savez déjà comment gérer cela.
Un exemple de ceci peut être vu dans le modèle de base de données pour Redmine, vous pouvez voir la table custom_fields, et la table custom_values - ce sont des parties de l'EAV qui permet d'étendre le système.
Notez que si vous trouvez que votre structure de table entière ressemble à EAV plutôt que relationnelle, vous voudrez peut-être examiner la version KV de NoSQL (cassandra, redis, mongo, ...). Sachez que ceux-ci viennent souvent avec d’ autres compromis dans leur conception qui peuvent ou non être appropriés à l’utilisation que vous en faites. Cependant, ils sont spécifiquement conçus avec l'intention d'une structure EAV.
Vous voudrez peut-être lire SQL vs NoSQL pour un système de gestion d'inventaire
En suivant cette approche avec une base de données NoSQL orientée document (divan, mongo), vous pouvez considérer chaque article d'inventaire comme un document sur un disque ... tout en un dans un document est rapide. En outre, le document est structuré de sorte que vous puissiez extraire rapidement une seule chose. D'autre part, rechercher dans tous les documents des éléments correspondant à un attribut particulier peut avoir des performances moindres (comparer avec "grep" contre tous les fichiers) ... c'est tout un compromis.
Une autre approche serait LDAP, dans laquelle on disposerait d'une base avec tous les éléments associés, mais on appliquerait également des classes d'objet supplémentaires pour les autres types d'éléments. (voir Inventaire du système avec LDAP )
Une fois que vous empruntez ce chemin, vous pouvez trouver quelque chose qui correspond exactement à ce que vous recherchez ... même si tout est assorti de compromis.
la source
6 ans plus tard
Maintenant que JSON dans Postgres est arrivé, nous avons une autre option, pour ceux qui utilisent Postgres. Si vous souhaitez uniquement attacher des données supplémentaires à un produit, vos besoins sont assez simples. Exemple:
Voici une introduction plus fluide à JSON dans Postgres: https://www.compose.com/articles/is-postgresql-votre-next-json-database/ .
Notez que Postgres stocke réellement JSONB, et non JSON en texte brut, et prend en charge les index sur les champs d’un document / champ JSONB, au cas où vous découvririez que vous souhaitiez réellement interroger ces données.
Notez également que les champs d'un champ JSONB ne peuvent pas être modifiés individuellement avec une requête UPDATE; vous devrez remplacer tout le contenu du champ JSONB.
Cette réponse ne répond peut-être pas directement à la question, mais elle offre une alternative au modèle EAV, qui devrait être envisagée par quiconque réfléchit à la question initiale.
la source
jsonb_set()
fonction dans Postgres 9.5 et versions ultérieures qui correspond exactement à cela. (L'article que vous avez lié à des liens renvoie à un article plus récent concernant les ajouts de fonctionnalités 9.5 .)Généralement, les gens regardent autrement si vous l'utilisez pour des tables de recherche ou dans d'autres situations où il est avantageux de ne pas avoir à créer de tables pour une ou deux valeurs stockées. La situation que vous décrivez, où vous stockez essentiellement les propriétés d'un élément, semble parfaitement normale (et normalisée). Élargir une table pour stocker un nombre variable d'attributs d'élément est une mauvaise idée.
Pour le cas général du stockage de données disparates dans une longue table mince ... Vous ne devriez pas avoir peur de créer de nouvelles tables si vous en avez besoin, et avoir juste une ou deux longues tables maigres n’est pas bien mieux que de ne deux courtes tables de graisse.
Cela dit, je suis notoire pour l’utilisation de tables EAV pour la journalisation. Ils ont une bonne utilité.
la source
EAV change le problème de la structure explicite, en perception implicite. Plutôt que de dire que X est un tableau avec les colonnes A et B. Vous sous-entendez que les colonnes A et B forment un tableau X. C'est l'inverse en un sens, mais il n'y a pas nécessairement de mappage un à un. Vous pourriez dire que A et B correspondent tous deux à des tables (ou types) X et Y. Cela pourrait être important dans le domaine plus impliqué où le contexte est important.
J'ai étudié Datomic pour ce type d'approche et je pense que c'est un système très utile et puissant avec des limites à ce que vous devriez en faire (pas que vous ne puissiez pas le faire).
Je suis d'accord avec EAV pour dire que EAV serait lent ou "te donner assez de corde pour te pendre". Au lieu de cela, je mettrais davantage l'accent sur les points forts d'EAV et si cela convient à votre espace de problèmes, vous devriez l'examiner.
Mon expérience est que c'est une merveilleuse approche presque sans contrainte pour la modélisation. Plus précisément, dans le cas de Datomic, ils imposent un ensemble sémantique au-dessus de tout. Toute décision de modélisation qui modélise une relation peut aller librement d'une à plusieurs sans avoir à redéfinir les colonnes / tableaux. Vous pouvez également revenir en arrière tant que la contrainte ne viole pas l'invariant. C'est tout pareil sous le capot.
Le problème avec EAV a été dans mon esprit dû à l’absence d’une implémentation telle que Datomic. Comme il s’agit d’une question sur EAV, je ne veux pas en parler à propos de Datomic, mais c’est une de ces choses où je pense qu’ils ont tout bien compris en ce qui concerne EAV.
la source