可以肯定地说EAV/CR数据库模型很糟糕。那就是说,
问题:应该使用哪种数据库模型,技术或模式来处理描述可在运行时更改的电子商务产品的“类”?
在一个优秀的电子商务数据库中,您将存储选项类别(如电视分辨率,然后为每台电视分辨率,但下一个产品可能不是电视,没有“电视分辨率”)。如何存储它们,有效搜索,并允许用户使用描述其产品的可变字段设置产品类型?如果搜索引擎发现客户通常根据控制台深度搜索电视,则可以在字段中添加控制台深度,然后在运行时为每种电视产品类型添加单个深度。
良好的电子商务应用程序中有一个很好的共同特征,它们显示一组产品,然后“向下钻取”侧面菜单,您可以看到“电视分辨率”作为标题,以及前五个最常见的电视找到的集合的解决方案。您单击一个,它只显示该分辨率的电视,允许您通过选择侧面菜单上的其他类别进一步向下钻取。这些选项将是在运行时添加的动态产品属性。</ p>
进一步讨论:
长话短说,互联网上是否有任何链接或模型描述可以“学术上”修复以下设置?我感谢Noel Kennedy建议的类别表,但需要比这更大。我在下面用不同的方式描述它,试图强调其意义。我可能需要进行视点校正来解决问题,或者我可能需要更深入地了解EAV / CR。
喜欢对EAV / CR模型的积极回应。我的开发人员都说杰弗里·肯普在下面提到了什么:“新实体必须由专业人士建模和设计”(脱离背景,阅读下面的回复)。问题是:
客户希望为产品添加属性有两个原因:
属性必须具有重要性,而不仅仅是关键字搜索。如果他们想要比较所有有“奶油糖霜”的蛋糕,他们可以点击蛋糕,点击生日主题,点击生奶油糖霜,然后检查所有有趣的蛋糕,知道他们都有奶油糖霜。这不仅仅是蛋糕,只是一个例子。
答案 0 :(得分:74)
我可以想到一些一般的利弊,有些情况下一个比另一个好:
选项1,EAV模型:
选项2,分别为每个实体建模:
选项3,组合(模型实体“正确”,但为某些/所有实体的自定义属性添加“扩展”)
* 我不确定选项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/PSDis not a good ecommerce platform/format. Magento/PSDis 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/PSDis an abysmal ecommerce platform/format. Having // worked on this code for several weeks now, my hate for Magento/PSDhas 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:
答案 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有许多缺点:
答案 9 :(得分:1)
我有一个稍微不同的问题:使用稀疏值(这可能是使用EAV的一个很好的理由)而不是许多属性,我想存储更像电子表格的东西。工作表中的列可以更改,但在工作表中,所有单元格都将包含数据(非稀疏)。
我做了一个small set of tests来测试两个设计:一个使用EAV,另一个使用Postgres ARRAY来存储单元格数据。
两个模式都在适当的列上有索引,并且规划器使用索引。
对于插入和查询,结果是array-based schema was an order of magnitude faster。从快速测试来看,它们似乎都是线性缩放的。但是,测试并不是很彻底。欢迎提出建议和要求 - 他们是麻省理工学院的许可证。