140

可以肯定地说EAV/CR数据库模型很糟糕。也就是说,

问题:应该使用什么数据库模型、技术或模式来处理描述电子商务产品的属性“类”,这些属性可以在运行时更改?

在一个好的电子商务数据库中,您将存储选项类别(例如电视分辨率,然后为每台电视提供一个分辨率,但下一个产品可能不是电视,也没有“电视分辨率”)。您如何存储它们、有效搜索并允许您的用户使用描述其产品的可变字段设置产品类型?如果搜索引擎发现客户通常根据控制台深度搜索电视,您可以将控制台深度添加到您的字段中,然后在运行时为每个电视产品类型添加单个深度。

优秀的电子商务应用程序有一个很好的共同特征,它们显示一组产品,然后有“向下钻取”侧菜单,您可以在其中看到“电视分辨率”作为标题,以及最常见的前五个电视分辨率发现集。您单击一个,它只显示该分辨率的电视,允许您通过选择侧面菜单上的其他类别进一步深入研究。这些选项将是在运行时添加的动态产品属性。

进一步讨论:

长话短说,互联网上是否有任何链接或模型描述可以“从学术上”解决以下设置? 我感谢 Noel Kennedy 提出了一个类别表,但需求可能不止于此。我在下面用不同的方式描述它,试图突出它的重要性。我可能需要进行视点校正来解决问题,或者我可能需要更深入地了解 EAV/CR。

喜欢对 EAV/CR 模型的积极响应。我的开发人员同事都说 Jeffrey Kemp 在下面谈到的内容:“新实体必须由专业人士建模和设计”(断章取意,请阅读下面的回复)。问题是:

  • 实体每周添加和删除属性
    (搜索关键字决定未来的属性)
  • 每周都有新实体到货
    (产品由零件组装而成)
  • 旧实体每周消失
    (存档、不太受欢迎、季节性)

客户想要为产品添加属性有两个原因:

  • 部门/关键词搜索/同类产品对比图
  • 结账前的消费产品配置

属性必须有意义,而不仅仅是关键字搜索。如果他们想比较所有有“奶油糖霜”的蛋糕,他们可以点击蛋糕,点击生日主题,点击奶油糖霜,然后检查所有有趣的蛋糕,知道它们都有奶油糖霜。这不是特定于蛋糕的,只是一个例子。

4

10 回答 10

75

我能想到一些一般的优点和缺点,在某些情况下,一种比另一种更好:

选项 1,EAV 型号:

  • 优点:设计和开发简单应用程序的时间更少
  • 优点:易于添加的新实体(甚至可能由用户添加?)
  • Pro:“通用”接口组件
  • 缺点:验证简单数据类型所需的复杂代码
  • 缺点:用于简单报告的更复杂的 SQL
  • 缺点:复杂的报告可能变得几乎不可能
  • 缺点:大型数据集的性能不佳

选项 2,分别为每个实体建模:

  • 缺点:收集需求和设计需要更多时间
  • 缺点:新实体必须由专业人士建模和设计
  • 缺点:每个实体的自定义界面组件
  • 优点:数据类型约束和验证易于实现
  • 优点:SQL 易于编写,易于理解和调试
  • 优点:即使是最复杂的报告也相对简单
  • Pro:大型数据集的最佳性能

选项 3,组合(“正确”模型实体,但为某些/所有实体的自定义属性添加“扩展”)

  • 优缺点:收集需求和设计所需的时间比选项 1 多,但可能不如选项 2 *
  • 缺点:新实体必须由专业人士建模和设计
  • 优点:以后可能很容易添加新属性
  • 缺点:验证简单数据类型所需的复杂代码(用于自定义属性)
  • 缺点:仍然需要自定义界面组件,但自定义属性可能会使用通用界面组件
  • 缺点:只要报告中包含任何自定义属性,SQL 就会变得复杂
  • 缺点:一般性能良好,除非您开始需要按自定义属性搜索或报告

*我不确定选项 3 是否一定会在设计阶段节省任何时间。

就我个人而言,我倾向于选项 2,并尽可能避免 EAV。但是,对于某些场景,用户需要 EAV 带来的灵活性;但这需要付出很大的代价。

于 2009-05-18T06:29:11.650 回答
64

可以肯定地说 EAV/CR 数据库模型很糟糕。

不,这不对。只是它们对关系数据库的使用效率低下。纯键/值存储非常适合此模型。

现在,对于您真正的问题:如何存储各种属性并使其可搜索?

只需使用 EAV。在您的情况下,这将是一张额外的桌子。在属性名称和值上都对其进行索引,大多数 RDBM 会在属性名称重复上使用前缀压缩,使其非常快速和紧凑。

当您使用 EAV/CR 替换“真实”字段时,它会变得丑陋。与每个工具一样,过度使用它是“坏的”,并给它一个坏形象。

于 2009-05-15T21:44:54.417 回答
16
// 在这一点上,我想花点时间和你谈谈 Magento/ Adobe PSD 格式。
// Magento/ PSD不是一个好的电子商务平台/格式。Magento/ PSD甚至不是一个糟糕的电子商务平台/格式。这么称呼它
// 侮辱其他不良电子商务平台/格式,例如 Zencart 或 OsCommerce。不,Magento/ PSD是一个糟糕的电子商务平台/格式。有
// 这段代码已经工作了几个星期了,我对 Magento/ PSD的仇恨已经变得熊熊燃烧
// 燃烧着一百万个太阳的强烈激情。

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

内部模型充其量是古怪的,就像有人将架构放入拼图游戏中,将其密封并放入油漆盒中……

现实世界:我正在开发一个中间件履行应用程序,这是获取地址信息的查询之一。

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'

懒惰地为订单提供准确的地址信息

--

摘要:仅在以下情况下使用 Magento:

  1. 你得到了一大袋钱
  2. 你必须
  3. 享受痛苦
于 2010-09-27T21:15:01.263 回答
15

我很惊讶没有人提到 NoSQL 数据库。

我从未在生产环境中练习过 NoSQL(刚刚测试了 MongoDB 并印象深刻),但 NoSQL 的重点在于能够将具有不同属性的项目保存在同一个“文档”中。

于 2011-04-05T23:10:29.747 回答
12

在性能不是主要要求的情况下,例如在 ETL 类型的应用程序中,EAV 具有另一个明显的优势:差异保存。

我已经实现了许多应用程序,其中最重要的要求是能够查看域对象从其第一个“版本”到当前状态的历史记录。如果该域对象具有大量属性,则意味着每次更改都需要将新行插入到其对应的表中(不是更新,因为历史记录会丢失,而是插入)。假设这个域对象是一个 Person,我有 500k Persons 要跟踪,在 Persons 生命周期中平均有 100 多个更改为各种属性。再加上只有 1 个主要域对象的应用程序很少见,您很快就会推测数据库的大小将迅速失控。

一个简单的解决方案是只保存对主要域对象的差异更改,而不是重复保存冗余信息。

所有模型都会随着时间的推移而变化,以反映新的业务需求。时期。使用 EAV 只是我们使用的工具之一;但它永远不应该被自动归类为“坏”。

于 2011-07-20T13:04:54.893 回答
3

我正在努力解决同样的问题。您可能会感兴趣查看以下关于两个现有电子商务解决方案的讨论:Magento (EAV) 和 Joomla(常规关系结构): https ://forum.virtuemart.net/index.php?topic=58686.0

看来,Magento 的 EAV 性能是真正的亮点。

这就是为什么我倾向于标准化结构。为了克服缺乏灵活性,我正在考虑在将来添加一些可以编辑的单独数据字典(XML 或单独的 DB 表),并基于此,用于显示和比较具有新属性集的产品类别的应用程序代码将是与 SQL 脚本一起生成。

这种架构似乎是这种情况下的最佳选择——同时灵活且高性能。

问题可能是在实时环境中频繁使用 ALTER TABLE。我正在使用 Postgres,因此它的 MVCC 和事务性 DDL 有望减轻痛苦。

于 2009-12-28T10:04:45.803 回答
2

我仍然投票支持在 EAV 的最低意义原子级别建模。让面向特定用户社区的标准、技术和应用程序来决定内容模型、属性的重复需求、粒度等。

于 2010-05-07T16:58:43.287 回答
2

如果它只是关于产品目录属性,因此对这些属性的验证要求相当有限,那么 EAV 唯一真正的缺点是查询性能,甚至当您的查询处理具有属性的多个“事物”(产品)时,这也是一个问题,查询“给我 ID 为 234 的产品的所有属性”的性能虽然不是最佳的,但仍然很快。

一种解决方案是仅将 SQL 数据库/EAV 模型用于产品目录的管理/编辑端,并通过一些过程将产品非规范化为使其可搜索的东西。由于您已经拥有属性,因此您很可能想要分面,这可能是 Solr 或 ElasticSearch。这种方法基本上避免了 EAV 模型的所有缺点,并且增加的复杂性仅限于在更新时将完整的产品序列化为 JSON。

于 2014-09-27T18:08:04.883 回答
2

EAV有很多缺点:

  1. 随着时间的推移性能下降 一旦应用程序中的数据量增长到超过一定大小,该数据的检索和操作可能会变得越来越低效。
  2. SQL 查询非常复杂且难以编写。
  3. 数据完整性问题。您不能为所有需要的字段定义外键。
  4. 您必须定义和维护自己的元数据。
于 2015-05-06T12:24:21.573 回答
1

我有一个稍微不同的问题:我想要存储更像电子表格的东西,而不是许多具有稀疏值的属性(这可能是使用 EAV 的一个很好的理由)。工作表中的列可以更改,但在工作表中,所有单元格都将包含数据(不是稀疏的)。

我做了一组测试来对两种设计进行基准测试:一种使用 EAV,另一种使用 Postgres ARRAY 存储单元数据。

EAV 在此处输入图像描述

大批 在此处输入图像描述

两种模式在适当的列上都有索引,并且索引由规划器使用。

事实证明,基于数组的模式对于插入和查询来说都快了一个数量级。从快速测试来看,两者似乎都是线性缩放的。不过,测试不是很彻底。欢迎提出建议和分叉 - 它们受 MIT 许可。

于 2016-03-07T05:12:58.260 回答