可以肯定地说EAV/CR数据库模型很糟糕 . 那说,
问题: What database model, technique, or pattern should be used to deal with "classes" of attributes describing e-commerce products which can be changed at run time?
在一个好的电子商务数据库中,您将存储选项类别(如电视分辨率,然后为每个电视分辨率,但下一个产品可能不是电视,没有“电视分辨率”) . 如何存储它们,有效搜索,并允许用户使用描述其产品的可变字段设置产品类型?如果搜索引擎发现客户通常根据控制台深度搜索电视,则可以向字段添加控制台深度,然后在运行时为每种电视产品类型添加单个深度 .
良好的电子商务应用程序中有一个很好的共同特征,它们显示一组产品,然后“向下钻取”侧面菜单,您可以看到“电视分辨率”作为 Headers ,以及前五个最常见的电视分辨率发现集 . 您单击一个,它只显示该分辨率的电视,允许您通过选择侧面菜单上的其他类别进一步向下钻取 . 这些选项是运行时添加的动态产品属性 .
Further discussion:
长话短说, are there any links out on the Internet or model descriptions that could "academically" fix the following setup? 我感谢Noel Kennedy建议的类别表,但需求可能更大 . 我在下面用不同的方式描述它,试图强调其意义 . 我可能需要进行视点校正来解决问题,或者我可能需要深入了解EAV / CR .
喜欢对EAV / CR模型的积极响应 . 我的开发人员都说杰弗里·肯普在下面提到了什么:“新实体必须由专业人士建模和设计”(脱离背景,阅读下面的回复) . 问题是:
-
个实体每周添加和删除属性
(搜索关键字决定未来的属性) -
新实体每周到达
(产品由零件组装) -
个实体每周都会消失
(存档,不太流行,季节性)
客户希望为产品添加属性有两个原因:
- 部门/关键字搜索/相似产品之间的比较图表
结账前 - 消费品配置
属性必须具有重要性,而不仅仅是关键字搜索 . 如果他们想要比较所有有“奶油糖霜”的蛋糕,他们可以点击蛋糕,点击生日主题,点击生奶油糖霜,然后检查所有有趣的蛋糕,知道他们都有奶油糖霜 . 这不仅仅是蛋糕,只是一个例子 .
10 回答
我可以想到一些一般的利弊,有些情况下一个比另一个好:
Option 1, EAV Model:
Pro:设计和开发简单应用程序的时间更少
Pro:易于添加的新实体(甚至可能被用户添加?)
Pro:"generic"界面组件
Con:验证简单数据类型所需的复杂代码
Con:简单报告的SQL要复杂得多
Con:复杂的报告几乎不可能
Con:大型数据集的性能不佳
Option 2, Modelling each entity separately:
Con:收集需求和设计需要更多时间
Con:新实体必须由专业人员建模和设计
Con:每个实体的自定义界面组件
Pro:数据类型约束和验证易于实现
Pro:SQL易于编写,易于理解和调试
亲:即使是最复杂的报道也相对简单
Pro:大数据集的最佳性能
Option 3, Combination (model entities "properly", but add "extensions" for custom attributes for some/all entities)
Pro / Con:收集要求和设计所需的时间比选项1多,但可能没有选项2 *那么多
Con:新实体必须由专业人员建模和设计
Pro:以后可能很容易添加新属性
Con:验证简单数据类型所需的复杂代码(用于自定义属性)
Con:仍然需要自定义界面组件,但自定义属性可以使用通用界面组件
Con:只要报表中包含任何自定义属性,SQL就会变得复杂
Con:一般表现良好,除非您开始需要按自定义属性搜索或报告
*我不确定选项3是否必然会在设计阶段节省任何时间 .
我个人倾向于选项2,尽可能避免使用EAV . 但是,对于某些情况,用户需要EAV附带的灵活性;但这需要很高的成本 .
不,这不对 . 只是它们对关系数据库的使用效率低下 . 纯粹的键/值存储可以很好地使用这个模型 .
现在,问你真正的问题:如何存储各种属性并让它们可搜索?
只需使用EAV . 在你的情况下,它将是一个额外的表 . 在属性名称和值上对其进行索引,大多数RDBM将对属性名称重复使用前缀压缩,使其非常快速和紧凑 .
当你用它来代替'真实'字段时,EAV / CR变得丑陋 . 与每个工具一样,过度使用它是“坏”的,并给它一个糟糕的图像 .
http://code.google.com/p/xee/source/browse/trunk/XeePhotoshopLoader.m?spec=svn28&r=11#107
内部模型充其量是古怪的,就像有人将模式放入一个沼泽游戏中,将其密封并将其放入油漆瓶中...
现实世界:我正在开发一个中间件实现应用程序,这里有一个获取地址信息的查询 .
懒惰地确定订单的地址信息
Summary: 仅在以下情况下使用Magento:
你得到了大笔钱
你必须
享受痛苦
我很惊讶没人提到NoSQL数据库 .
我从来没有在 生产环境 环境中练习NoSQL(只测试了MongoDB并且给人留下了深刻的印象)但NoSQL的重点在于能够在同一个“文档”中保存具有不同属性的项目 .
在性能不是主要要求的情况下,如在ETL类型的应用中,EAV具有另一个明显的优势:差异节省 .
我已经实现了许多应用程序,其中一个主要的要求是能够查看域对象从其第一个“版本”到其当前状态的历史记录 . 如果该域对象具有大量属性,则意味着每次更改都需要在其对应的表中插入新行(不是更新,因为历史记录将丢失,而是插入) . 假设这个域对象是一个Person,我有500k人跟踪人员生命周期平均100次变化到各种属性 . 再加上罕见的是只有一个主要域对象的应用程序,你很快就会猜测数据库的大小会很快失控 .
一个简单的解决方案是仅保存主要域对象的差异更改,而不是重复保存冗余信息 .
所有模型都会随着时间而变化,以反映新的业务需期 . 使用EAV只是我们使用盒子中的工具之一;但它永远不应被自动归类为“坏” .
我正在努力解决同样的问题 . 您可能有兴趣查看以下关于两个现有电子商务解决方案的讨论:Magento(EAV)和Joomla(常规关系结构):https://forum.virtuemart.net/index.php?topic=58686.0
看来,Magento的EAV性能是一个真正的表现 .
这就是我倾向于标准化结构的原因 . 为了克服缺乏灵活性,我正考虑在将来添加一些单独的数据字典(XML或单独的数据库表),可以编辑,并在此基础上,用于显示和比较产品类别与新属性集的应用程序代码将是与SQL脚本一起生成 .
在这种情况下,这种架构似乎是甜点 - 同时具有灵活性和高性能 .
问题可能是在实时环境中经常使用ALTER TABLE . 我正在使用Postgres,因此它的MVCC和事务DDL将有望缓解痛苦 .
我仍然投票给EAV的最低有意义的原子级建模 . 让标准,技术和应用程序适应某些用户社区,以决定内容模型,属性,谷物等的重复需求 .
如果只是产品目录属性,因此对这些属性的验证要求相当有限,EAV唯一真正的缺点就是查询性能,甚至当查询处理带有属性的多个“东西”(产品)时,这只是一个问题,查询的性能“给我ID为234的产品的所有属性”,而不是最优的仍然很快 .
一种解决方案是仅将SQL数据库/ EAV模型用于产品目录的管理/编辑方面,并使某些过程将产品非规范化为使其可搜索的内容 . 由于你已经有了属性,因此很可能你想要分面,这个东西可能是Solr或ElasticSearch . 这种方法基本上避免了EAV模型的所有缺点,并且增加的复杂性仅限于此在更新时将完整产品序列化为JSON .
EAV有许多缺点:
随着时间的推移性能下降一旦应用程序中的数据量增长超过一定大小,对该数据的检索和操作可能会变得越来越低效 .
SQL查询非常复杂且难以编写 .
数据完整性问题 . 您无法为所需的所有字段定义外键 .
您必须定义和维护自己的元数据 .
我有一个稍微不同的问题:使用稀疏值(这可能是使用EAV的一个很好的理由)而不是许多属性,我想存储更像电子表格的东西 . 工作表中的列可以更改,但在工作表中,所有单元格都将包含数据(不是稀疏的) .
我做了一个small set of tests来测试两个设计:一个使用EAV,另一个使用Postgres ARRAY来存储细胞数据 .
EAV
Array
两个模式都在适当的列上具有索引,并且规划器使用索引 .
事实证明,插入和查询都是array-based schema was an order of magnitude faster . 从快速测试来看,它们似乎都是线性缩放的 . 这些测试不是麻省理工学院的许可证 .