实体属性值数据库与严格关系模型电子商务

时间:2009-05-15 20:48:36

标签: sql database design-patterns entity-attribute-value key-value

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

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

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

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

进一步讨论:

长话短说,互联网上是否有任何链接或模型描述可以“学术上”修复以下设置?我感谢Noel Kennedy建议的类别表,但需要比这更大。我在下面用不同的方式描述它,试图强调其意义。我可能需要进行视点校正来解决问题,或者我可能需要更深入地了解EAV / CR。

喜欢对EAV / CR模型的积极回应。我的开发人员都说杰弗里·肯普在下面提到了什么:“新实体必须由专业人士建模和设计”(脱离背景,阅读下面的回复)。问题是:

  • 实体每周添加和删除属性
    (搜索关键字决定未来属性)
  • 新实体每周到达(产品由部件组装)
  • 旧实体每周消失(存档,不太受欢迎,季节性)

客户希望为产品添加属性有两个原因:

  • 部门/关键字搜索/同类产品之间的比较图表
  • 结账前的消费品配置

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

10 个答案:

答案 0 :(得分:74)

我可以想到一些一般的利弊,有些情况下一个比另一个好:

选项1,EAV模型:

  • Pro:设计和开发简单应用程序的时间更短
  • Pro:易于添加的新实体(甚至可能 用户添加?)
  • Pro:“通用”界面组件
  • Con:验证简单数据类型所需的复杂代码
  • Con:简单的SQL要复杂得多 报告
  • Con:复杂的报道几乎可以成为 不可能
  • Con:大型数据集的性能不佳

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

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

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

  • Pro / Con:收集要求和设计所需的时间比选项1多,但可能没有选项2 *
  • Con:新实体必须由专业人士建模和设计
  • Pro:以后可以轻松添加新属性
  • Con:验证简单数据类型(对于自定义属性)所需的复杂代码
  • Con:仍然需要自定义界面组件,但自定义属性可以使用通用界面组件
  • Con:只要报表中包含任何自定义属性,SQL就会变得复杂
  • Con:通常情况良好,除非您开始需要按自定义属性进行搜索或报告

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

就我个人而言,我会倾向于选项2,尽可能避免使用EAV。但是,对于某些情况,用户需要EAV附带的灵活性;但这需要很高的成本。

答案 1 :(得分:61)

  

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

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

现在,问你真正的问题:如何存储各种属性并让它们可以搜索?

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

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

答案 2 :(得分:15)

// At this point, I'd like to take a moment to speak to you about the Magento/Adobe PSD format.
// Magento/PSD is not a good ecommerce platform/format. Magento/PSD is not even a bad ecommerce platform/format. Calling it such would be an
// insult to other bad ecommerce platform/formats, such as Zencart or OsCommerce. No, Magento/PSD is an abysmal ecommerce platform/format. Having
// worked on this code for several weeks now, my hate for Magento/PSD has grown to a raging fire
// that burns with the fierce passion of a million suns.

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. 享受痛苦

答案 3 :(得分:15)

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

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

答案 4 :(得分:11)

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

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

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

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

答案 5 :(得分:3)

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

看来,Magento的EAV性能是一个真正的显示器。

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

这种架构似乎是这种情况下的甜点 - 同时具有灵活性和高效性。

问题可能是在实时环境中经常使用ALTER TABLE。我正在使用Postgres,因此它的MVCC和事务性DDL将有望缓解痛苦。

答案 6 :(得分:2)

我仍然投票给EAV的最低有意义的原子级建模。让标准,技术和应用程序适应某些用户社区,以决定内容模型,属性,谷物等的重复需求。

答案 7 :(得分:2)

如果它只是关于产品目录属性,因此这些属性的验证要求相当有限,EAV唯一真正的缺点是查询性能,即使这只是一个问题,当您的查询处理多个&#时34;东西&#34; (产品)带有属性,查询的性能&#34;给我ID为234&#34;的产品的所有属性。虽然不是最优的仍然很快。

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

答案 8 :(得分:2)

EAV有许多缺点:

  1. 性能随时间而下降 一旦应用程序中的数据量增长超过一定大小,对数据的检索和操作可能会变得越来越低效。
  2. SQL查询非常复杂,难以编写。
  3. 数据完整性问题。 您无法为所需的所有字段定义外键。
  4. 您必须定义和维护自己的元数据。

答案 9 :(得分:1)

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

我做了一个small set of tests来测试两个设计:一个使用EAV,另一个使用Postgres ARRAY来存储单元格数据。

<强> EAV enter image description here

<强>阵列 enter image description here

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

对于插入和查询,结果是array-based schema was an order of magnitude faster。从快速测试来看,它们似乎都是线性缩放的。但是,测试并不是很彻底。欢迎提出建议和要求 - 他们是麻省理工学院的许可证。