实体-属性-值表设计

29

我目前正在为电商平台的产品部分设计数据库结构,需要设计一种能够销售无限种不同类型产品和无限个不同属性的方法。

例如,笔记本电脑的属性可能包括内存、屏幕尺寸、重量等,书籍的属性则可能包括作者、ISBN、出版社等。

看起来EAV结构可能是最合适的。

  • 选择一个产品
  • 产品归属于属性集合
  • 属性集合包含属性x和y
    • 属性x为日期时间数据类型(值存储在attribute_values_datetime表中)
    • 属性y为整数数据类型(值存储在attribute_values_int表中)
  • 每个属性定义都指示了其数据类型(例如,x具有列类型->日期时间)

假设以上内容,我是否可以将选择与attribute_values_datetime表连接以获取正确的数据,而无需获取结果集并构建第二个查询(因为已知表格)?这种类型的查询构建会有很大的性能损失还是下面的更合适(虽然功能较少)

  • 选择一个产品
  • 产品归属于属性集合
  • 属性集合包含属性x和y
    • 属性x为日期时间数据类型,但在attribute_values表中存储为TEXT
    • 属性y为整数数据类型,但在attribute_values表中存储为TEXT

7
不要使用EAV。不用考虑性能问题(仅会增长的大型表),而是考虑如何对其进行查询。在大多数情况下,EAV是规范化过度了。 - Oded
7
我倾向于同意 @Oded 的观点,你最终会在数据库中建立另一个数据库。我想知道大型在线零售商采用了什么方法(好的那些)。 - Jodrell
4
使用数据库作为数据库... 为你最终拥有的 实际 产品类型创建表格。如果面对不合理的需求,要进行反驳——“无限数量的不同产品类型和属性” 对我来说肯定是不合理的。从业务方面获取一些预估限制。 - Oded
5
EAV与规范化无关。没有任何分解规则指出:"将属性名称作为数据存储在表格的一行中,并将其值,无论数据类型如何,存储为同一行中的varchar(n)"。然而这可能是过度抽象。 - Mike Sherrill 'Cat Recall'
2
@Oded,没有人能够遵循规范化的规则,无论是过度还是不足,然后到达EAV。只有当他们完全不理解规范化的含义时,才能到达EAV。存储EAV数据的物理表和试图模拟它的虚拟表都无法成为关系。如果它不是一个关系,那么你就不能将表放入任何正常形式中。这是一个前提条件,就像存在“第0正常形式”一样。 - Bill Karwin
显示剩余7条评论
3个回答

34
我将提供与大多数评论相反的观点。虽然在SO、DBA.SE和其他地方已经有很多次详细解释了EAV的所有问题,因此EAV是邪恶的,但是有一个非常常见的应用程序,对于这个应用程序来说,EAV的大部分问题基本上都不相关,而EAV的(少数)优点非常相关。这个应用程序是在线产品目录。
EAV的主要问题在于它不能让数据库真正擅长做的事情,即通过在模式中排列它们来帮助为不同实体的不同信息属性提供适当的上下文。拥有模式带来了许多许多关于访问、解释和强制执行数据完整性的优势。
产品目录的事实是,产品的属性几乎完全与目录系统本身无关。产品目录系统最多只会使用产品属性进行三件事情。
1.以{属性名称}:{属性值}的形式向最终用户显示产品属性列表。 2.在比较网格中显示多个产品的属性,其中不同产品的属性彼此对齐(产品通常是列,属性通常是行)。 3.根据特定的属性/值组合驱动某些规则(例如定价)。
如果您的系统只是重复语义上不相关(对于系统而言)的信息,则该信息的模式基本上是无用的。实际上,在在线产品目录中,模式会妨碍您,特别是如果您的目录有许多不同类型的产品,因为您总是需要回到模式中进行调整,以允许新的产品类别或属性类型。因为使用方式的不同,甚至产品目录中属性值的数据类型也不一定(非常)重要。对于某些属性,您可能希望强制实施约束条件,例如“必须是数字”或“必须来自此列表{...}”。这取决于属性一致性对目录的重要性以及您想要的实现的复杂程度。根据几家在线零售商的产品目录,我认为大多数人准备放弃简单性以换取一致性。
是的,EAV很邪恶,除非它不邪恶。

如果我们使用 eav,有什么措施可以防止性能问题?如果我们有成千上万的产品,那么使用 eav 一定会导致性能问题。 - fresher
1
@PhpBeginner 为什么你说使用EAV作为产品目录时性能问题是不可避免的?我认为这不是一个公正的评论。请具体说明哪些方面会表现更差?这种概括恰恰是我在这个答案中所谈论的。对于大多数应用程序来说,EAV确实是有害的。但在线产品目录并不是其中之一。在这种特定情况下,你不能说“EAV很慢”,或者“EAV使你的查询变得复杂”,或者“EAV从数据中删除了含义”或其他通常有效的EAV批评。 - Joel Brown

2
我不知道这应该是一个评论还是回答。无论如何,我来说一下。
我不确定你正在构建什么。但是,你是否看过Magento EAV数据库结构?是的,它可能会很慢,查询可能会很大,但对我们来说,优点大于缺点。另一方面,Magento负责查询。
我们正在将我们的在线商店(中大型商店)迁移到使用Magento,并且目前我们对EAV方法非常满意。

2
是的,通常在组装EAV模型的查询时会有很大的惩罚。检查数据的自洽性会有更大的性能惩罚,因为DBMS无法为您执行此操作。如果出现问题,DBMS无法告诉您。
采用更传统的数据库设计(如Oded在评论中建议的),DBMS可以确保数据库中的数据更加一致。我强烈建议使用常规(非EAV)设计。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接