可以肯定地说,EAV / CR数据库模型是错误的。就是说,

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

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

有一个优秀的电子商务应用程序中的一个很好的共同功能,即显示一组产品,然后具有“向下钻取”侧边菜单,您可以在其中看到“电视分辨率”作为标题,以及找到的前5个最常用的电视分辨率。您单击一个,它仅显示该分辨率的电视,从而允许您通过在侧面菜单上选择其他类别来进一步向下钻取。这些选项将是在运行时添加的动态产品属性。<​​br />
进一步的讨论:

长话短说,Internet上是否存在任何链接或模型描述, “学术上”修复以下设置?我感谢诺埃尔·肯尼迪(Noel Kennedy)提出了类别表,但需求可能更大。我在下面以另一种方式描述它,以强调其重要性。我可能需要进行视点校正才能解决该问题,或者可能需要更深入地研究EAV / CR。

喜欢对EAV / CR模型的积极回应。我的所有开发人员都说以下是Jeffrey Kemp谈到的内容:“新实体必须由专业人员建模和设计”(出于上下文考虑,请在下面阅读他的回答)。问题是:


实体每周添加和删除属性(搜索关键字决定未来的属性)

新实体每周到达(产品由零件组装而成)

旧实体每周消失(存档,不那么受欢迎) ,季节性)


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


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

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

评论

为什么只用一个带有外键引用自己的“类别”表呢?

说EAV数据库模型不好是不安全也不精确的,因为它非常适合某些应用程序。

如果您使用Entity Framework 4中的父对象来装饰具有各种属性的各种对象怎么办?它如何持久化那些对象?

刚才提到这篇关于一位顾问在基于EAV极端版本的系统上的经验的精彩文章。阅读! simple-talk.com/opinion/opinion-pieces/bad-carma

EAV是一个非常可行的数据库模型。我正在像您一样解决类似的问题,而解决方案是EAV。我会推荐以下文章:sqlblog.com/blogs/aaron_bertrand/archive/2009/11/19/…

#1 楼

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

选项1,EAV模型:


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

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


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

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


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

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

我个人将倾向于选择2,并尽可能避免使用EAV。但是,在某些情况下,用户需要EAV随附的灵活性。但这要付出巨大的代价。

评论


如果您有一个带有索引的文本值1-n的表,然后在C#(在ram中)中将所需内容映射到所需内容,该怎么办。它仍将像EAV一样工作,但“匹配项”将是域模型。有点像序列化,但是您可以在索引文本字段上使用SQL选择。每个记录没有多个选择。所有的“成本”都发生在RAM中。

–扎卡里·斯科特(Zachary Scott)
2010年6月15日,下午3:06

@Zim,听起来很像选项3。每一行都有1-n个额外的“通用”列,并且存储在其中的数据在应用程序级别进行解释。将一条记录的所有数据都放在一个地方,可以提高性能。但是,与这些列有关的元数据需要存储在某个地方,这是成本增加的地方。当然,我们可以将元数据缓存在ram中,但是与直接在应用程序代码中对域进行建模相比,它的成本仍然更高。当然比完全成熟的EAV模型要好!

–杰弗里·肯普(Jeffrey Kemp)
2010年6月15日,11:52

+10000好答案。如今,人们无视数据库设计和需求收集。他们宁愿多写一百倍的代码行,而这会花费一些时间来进行良好的设计。

–图兰斯·科尔多瓦(TulainsCórdova)
2014年8月17日,下午3:56

如果仅提供选项1的结构,则不需要为EAV选项(1)设计更多的关系选项(2),并且关系接口是从描述该结构的元数据继承的。这将删除所有选项2缺点。但是,您忘记了唯一的实际缺点:DDL管理表太慢。

–philipxy
15年8月29日在11:44



嗨@philipxy,我没有说“更多设计”。 EAV的存在理由是(大概)系统设计师可以在设计模型上花费更少的时间,而将设计工作留给以后的“用户”(由于缺乏专业设计,导致选项1列出了缺点) 。如果EAV不能为设计人员节省成本,那只会增加更多的燃料,从而无法控制EAV。另外,我不同意DDL太慢-因为仅应很少使用DDL(即修复模型中的错误或实现新功能),因此DDL的性能应该相对不重要。

–杰弗里·肯普(Jeffrey Kemp)
2015年8月31日在1:19



#2 楼


可以肯定地说,EAV / CR数据库模型是错误的。


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

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

只使用EAV。在您的情况下,它将是一个额外的表。在属性名称和值上对其进行索引,大多数RDBM都会在属性名称重复项上使用前缀压缩,从而使它真正快速而紧凑。

当您用它替换'真实”字段。与每种工具一样,过度使用它是“不好的”,并给它留下不好的印象。

评论


所以问题是我为我的类别之一增加了15个字段,在eav模型中,它需要16个join +主表,因此要进行左左16个连接以搜索3-4百万个记录中的产品(如果需要,则有16个)。一个人们出售二手产品的网站)那么它的性能较低吗?

– babak faghihian
15年10月28日在14:15

如果已经定义了这些“附加字段”,那么绝对最好将其作为“真实字段”。当然,在一个大型查询中进行无数次的联接将造成沉重的负担(但仍然可以!)。在繁重的元数据项目中,我所做的是每个“主要项目”允许任意数量的“标签”(作为EAV记录),但是“大型查询”仅选择一些预定义的标签名,从而限制了连接的总数(当前通常只有4个标签和大约5个其他联接),并且当用户选择特定项目时,它将获取所有相关的内容,但仅包含单个项目。

–哈维尔
15-10-28在19:43



但是,当然,该特定系统当前正在移植到hstore字段(这正是我们使用PostgreSQL的原因之一)

–哈维尔
15-10-28在19:47

#3 楼

// 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:


您将获得大笔金钱
必须
享受痛苦


评论


这是一篇较旧的文章,但我希望我在3个月前为一个客户启动Magento项目时就已经发现了。 +1令人难以置信的/摇摇晃晃类比!

– Trevorc
2011年1月12日在21:52

有趣的是,magento似乎是电子商务系统中的王者。也许只是营销很好

– Herr
2011年8月17日在9:22

Magento并不因维护级别而流行,而是具有自定义功能,允许任何人无需更改架构或进行任何修改即可实现新功能。此功能需要付费。

–迭戈·门德斯(Diego Mendes)
2015年7月27日在3:03



如果您想避免FE和BE造成三倍痛苦和重重痛苦,请远离Magento 2

–TheBlackBenzKid
17年8月21日在7:45

#4 楼

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

我从未在生产环境中实践过NoSQL(刚刚经过测试的MongoDB并给人留下了深刻的印象),但是NoSQL的全部目的是能够保存具有不同属性的项目在同一“文档”中。

评论


考虑到对MongoDB的写入需要数据库级别的锁定,这对于并发生产流量意味着什么。

– Bill Karwin
2013年3月13日在21:22

考虑锁定持续时间约为微秒。

– Hello World
15年1月2日,16:06

#5 楼

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

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

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

所有模型都会随时间而变化,以反映新的业务需求。期。使用EAV只是我们工具箱中要使用的工具之一;但绝对不能将其自动分类为“不良”。

评论


+1表示“使用EAV只是我们工具箱中要使用的工具之一;但永远不要将其自动归类为“不良”。

–渔获
16年7月26日在20:42

顺便说一句,这称为SCD(尺寸变化缓慢)。同样,对于具有此属性的属性,比特时间要求(类型4 SCD的特定情况)也需要EAV模式。请记住,99%的NoSQL没有本机联接,因此,如果需要使用这种类型的数据进行“实时”联接,则只有EAV可行。

–考伯特
17年7月12日在4:27

#6 楼

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

Magento的EAV性能似乎是真正的佼佼者。

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

在这种情况下,这种架构似乎是最有效的选择-同时具有灵活性和高性能。

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

#7 楼

我仍然投票支持在EAV的最低意义的原子级别上进行建模。让适合特定用户群体的标准,技术和应用程序决定内容模型,属性,粒度的重复需求等。

#8 楼

如果只涉及产品目录属性,因此对这些属性的验证要求受到很大限制,则EAV的唯一真正缺点就是查询性能,即使当您的查询处理带有属性的多个“事物”(产品)时,这也是一个问题,查询“为我提供ID为234的产品的所有属性”的性能虽然不是最佳,但仍然非常快。

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

#9 楼

EAV具有许多缺点:


随着时间的推移性能会下降
一旦应用程序中的数据量增长到超过一定大小,该数据的检索和处理就可能变得效率越来越低。
SQL查询非常复杂且难以编写。
数据完整性问题。
不能为所有需要的字段定义外键。
必须定义和维护自己的元数据。


评论


1.大多数关系数据库也是如此。这就是为什么创建分片的原因。 2.数据建模可能很复杂且难以实现。我花了数月至数月的等待OLAP多维数据集架构更改。 3.现在基本上已经在软件中完成了。4.无论如何,在对关系模式进行建模时,都必须在“ ERwin,Excel和Visio中”执行此操作。

–考伯特
17年7月12日在4:28



#10 楼

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

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

EAV




两种模式都有适当的索引列,索引由计划程序使用。

事实证明,对于插入和查询而言,基于数组的架构要快一个数量级。从快速测试来看,似乎两者均呈线性比例。测试不是很彻底。欢迎提出建议和建议-它们已获得MIT许可。

评论


您如何在数组模型的工作表列(即vlookup)上进行联接?您不必编写自己的数组合并排序功能吗?如果您使用单元格的sheet_id + x坐标+ y坐标作为单元格值的键,则高度怀疑它与预编译的合并排序一样好。 (要模拟excel,请为x坐标预生成一个查询表,其中0-18278是A-ZZZ列(excel的最大值为16384)),然后可以选择sheet_id = uuid和x-coord = 0和y-coord的值<1001以获取col A的前1000行。

–考伯特
17年7月12日在4:48

@cowbert你是对的;实际上,我只是加载我感兴趣的列并在Python中进行联接。松弛!

–z0r
17年7月13日在7:52