一尘不染

实体-属性-值表设计

mysql

我目前正在为电子商务平台的产品部分设计数据库结构。它的设计方式应使得可以销售无限数量的具有不同属性的不同类型的产品。

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

看来,EAV结构将是最合适的。

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

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

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

阅读 409

收藏
2020-05-17

共1个答案

一尘不染

我将对这个问题上的大多数评论提出相反的意见。尽管出于各种原因, EAV都是EVIL
,但您可以在SO和DBA.SE以及其他地方找到很多详尽的解释,但在一个真正普通的应用程序中,EAV的大部分错误与这些无关紧要,并且(很少)EAV的优势与之息息相关。该应用程序是在线产品目录。

EAV的主要问题在于,它不允许数据库执行其真正擅长的工作,这通过将它们排列在一个 架构中
,有助于为有关不同实体的信息的不同属性提供适当的上下文。拥有模式带来了许多有关访问,解释和加强数据完整性的优点。

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

  1. 在列表中向最终用户显示产品属性,格式为:{属性名称}:{属性值}。

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

  3. 根据特定的属性/值组合为某事物(例如定价)制定规则。

如果您的系统所做的只是反义(与系统)在语义上不相关的信息,则该信息的模式基本上是无用的。实际上,该模式 会妨碍
在线产品目录的运行,尤其是当您的目录中有许多不同类型的产品时,因为您总是必须回到该模式中进行修改才能允许使用新的产品类别或属性类型。

由于使用方式的原因,即使产品目录中的属性值的数据类型也不一定(非常重要)。对于某些属性,您可能要施加约束,例如“必须为数字”或“必须来自此列表{…}”。这取决于属性一致性对目录的重要性以及您希望实现的复杂程度。查看几家在线零售商的产品目录,我会说大多数人都准备权衡简单性和一致性。

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

2020-05-17