27

我目前正在为电子商务平台的产品部分设计数据库结构。它需要以这样一种方式设计,即可以销售具有无限数量不同属性的无限数量的不同类型的产品。

例如,笔记本电脑的属性可以是 RAM、屏幕尺寸、重量等。一本书的属性可以是 Author、ISBN、Publisher 等。

似乎 EAV 结构是最合适的。

  • 选择一个产品
  • 产品属于属性集
  • 属性集包含属性 x 和 y
    • 属性 x 是数据类型 datetime(存储在 attribute_values_datetime 中的值)
    • 属性 y 是数据类型 int(值存储在 attribute_values_int 中)
  • 每个属性定义表示类型(即,x 具有列类型 -> 日期类型)

假设上述情况,我是否可以将选择加入 attribute_values_datetime 表以获得正确的数据,而无需获取结果集并在该表已知的情况下构建第二个查询?构造这种类型的查询是否会对性能产生很大影响,或者下面的查询是否更合适(尽管功能较少)

  • 选择一个产品
  • 产品属于属性集
  • 属性集包含属性 x 和 y
    • 属性 x 是数据类型 datetime,但在 attribute_values 中存储为 TEXT
    • 属性 y 是数据类型 int 但在属性值中存储为 TEXT
4

3 回答 3

34

我将对这个问题的大多数评论提出相反的意见。虽然EAV 是邪恶的,因为您可以在 SO 和 DBA.SE 和其他地方找到多次详细解释的所有原因,但有一个非常常见的应用程序,其中 EAV 的大多数问题在很大程度上是无关紧要的,并且 (少数)EAV 的优势非常密切。该应用程序是在线产品目录。

EAV 的主要问题是它不会让数据库做它真正擅长的事情,这有助于通过将不同实体的信息的不同属性安排在模式中来为它们提供适当的上下文。拥有模式可以在访问、解释和强制数据完整性方面带来许多优势。

关于产品目录的事实是,产品的属性几乎与目录系统本身完全无关。产品目录系统(最多)对产品属性做三件事。

  1. 以列表形式向最终用户显示产品属性:{属性名称}:{属性值}。

  2. 在比较网格中显示多个产品的属性,其中不同产品的属性相互排列(产品通常是列,属性通常是行)

  3. 基于特定属性/值组合的某些东西(例如定价)的驱动规则。

如果您的系统所做的只是反刍与语义无关的信息(与系统无关),那么该信息的模式基本上是无用的。事实上,模式妨碍了在线产品目录,尤其是当您的目录包含许多不同类型的产品时,因为您总是不得不返回模式来修改它以允许新的产品类别或属性类型.

由于它的使用方式,即使产品目录中属性值的数据类型也不一定(至关重要)重要。对于某些属性,您可能需要施加约束,例如“必须是数字”或“必须来自此列表 {...}”。这取决于属性一致性对您的目录的重要性以及您希望实现的详细程度。看看几家在线零售商的产品目录,我想说大多数人都准备好以简单性换取一致性。

是的,EAV 是邪恶的,除非它不是。

于 2012-08-15T15:13:03.197 回答
2

我不知道这应该是评论还是答案。尽管如此,我还是走了。

我不知道你到底在建什么。但是您是否看过Magento EAV 数据库结构?是的,它可能很慢,查询可能很大,但对我们来说,优点多于缺点。另一方面,magento 负责查询。

我们正在将我们的在线商店(大中型商店)迁移到使用 Magento,目前我们对 EAV 方法非常满意。

于 2012-08-02T14:23:09.783 回答
2

是的,在为 EAV 模型组装查询时通常会有很大的损失。检查数据的自我一致性会带来更大的性能损失,因为 DBMS 无法为您做这件事。如果出现问题,DBMS 无法告诉您。

使用更正统的数据库设计,正如Oded在评论中推荐的那样,DBMS 确保数据库中的数据更加接近一致。我强烈建议使用常规(非 EAV)设计。

于 2012-08-12T05:00:13.460 回答