Dav*_*her 7 architecture database-design system-design entity-attribute-value
SQL中的Entity-Attribute-Value数据库设计的主要缺点似乎都与能够高效,快速地查询和报告数据有关.我读到的关于该主题的大部分信息都警告不要因为这些问题而实施EAV以及几乎所有应用程序的查询/报告的共性.
我目前正在设计一个系统,其中一个实体的字段在设计/编译时是未知的,并由系统的最终用户定义.EAV似乎非常适合这个要求,但由于我所读到的问题,我对实施它犹豫不决,因为这个系统也有一些非常繁重的报告要求.我想我已经找到了解决这个问题的方法,但是想向SO社区提出这个问题.
鉴于典型的规范化数据库(OLTP)仍然不总是运行报告的最佳选择,一个好的做法似乎是拥有一个"报告"数据库(OLAP),其中来自规范化数据库的数据被复制到,广泛索引,以及可能非规范化以便于查询.是否可以使用相同的想法来解决EAV设计的缺点?
我看到的主要缺点是将数据从EAV数据库传输到报告的复杂性增加,因为您可能最终必须在EAV数据库中定义新字段时更改报告数据库中的表.但这几乎是不可能的,并且似乎是EAV设计提高灵活性的可接受的权衡.如果我使用非SQL数据存储(即CouchDB或类似的)用于主数据存储,这种缺点也存在,因为所有标准报告工具都期望SQL后端进行查询.
如果您有一个单独的报告数据库用于查询,那么EAV系统的问题是否会消失?
编辑:感谢您的评论到目前为止.我正在研究的系统的一个重要事项是,我真的只是在谈论为其中一个实体使用EAV,而不是系统中的所有实体.
系统的全部要点是能够从多个不同的源提取数据,这些数据是提前未知的,并且会对数据进行处理以获得关于特定实体的一些"最知名"数据.因此,我正在处理的每个"领域"都是多值的,我还需要跟踪每个领域的历史记录.对于这种情况的标准化设计最终是每个字段1个表格,这使得查询它无论如何都很痛苦.
以下是我正在查看的表格模式和示例数据(显然与我正在处理的内容有所不同,但我认为它很好地说明了这一点):
EAV表
Person
-------------------
- Id - Name -
-------------------
- 123 - Joe Smith -
-------------------
Person_Value
-------------------------------------------------------------------
- PersonId - Source - Field - Value - EffectiveDate -
-------------------------------------------------------------------
- 123 - CIA - HomeAddress - 123 Cherry Ln - 2010-03-26 -
- 123 - DMV - HomeAddress - 561 Stoney Rd - 2010-02-15 -
- 123 - FBI - HomeAddress - 676 Lancas Dr - 2010-03-01 -
-------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
报告表
Person_Denormalized
----------------------------------------------------------------------------------------
- Id - Name - HomeAddress - HomeAddress_Confidence - HomeAddress_EffectiveDate -
----------------------------------------------------------------------------------------
- 123 - Joe Smith - 123 Cherry Ln - 0.713 - 2010-03-26 -
----------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
规范化设计
Person
-------------------
- Id - Name -
-------------------
- 123 - Joe Smith -
-------------------
Person_HomeAddress
------------------------------------------------------
- PersonId - Source - Value - Effective Date -
------------------------------------------------------
- 123 - CIA - 123 Cherry Ln - 2010-03-26 -
- 123 - DMV - 561 Stoney Rd - 2010-02-15 -
- 123 - FBI - 676 Lancas Dr - 2010-03-01 -
------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
这里的"置信度"字段是使用逻辑生成的,无法使用SQL轻松表达(如果有的话),因此除了插入新值之外,我最常用的操作是为所有字段提取有关人员的所有数据,这样我就可以生成记录.报告表.这在EAV模型中实际上更容易,因为我可以进行单个查询.在规范化设计中,我最终每个字段必须进行1次查询,以避免大量笛卡尔积将它们加在一起.
在这个方案中,首先我们提出了一个系统,允许用户存储任何类型的数据,无论其结构如何,并且无论将来的用途如何.然后,当得到报告的时候,我们必须弄清楚我们得到了什么,以及它与我们需要的相关.
既然你明确地将问题的本质归因于"在这个方案中",那么在我看来,EAV的问题确实是由于EAV 本身造成的.
事实上,想一想:"一个允许用户存储任何类型数据的系统"相当于一个允许用户只定义其relvars的系统.但是该系统的哪个部分允许用户定义每个属性的约束?哎呀,EAV人群似乎错过了一个不那么重要的数据管理方面,似乎......
小智 3
简短的回答 - 是的,报告数据库是解决 EAV 数据模型报告问题的合理方法。
我花了很多年的时间研究一个信息管理解决方案,该解决方案允许最终用户完全自由地定义自己的数据模型,其中模式和数据都使用 EAV 模型存储。有趣的是,该产品提供了用于满足报告需求的元模式对象(例如提供对象导航的图表、执行投影的视图等)。这意味着最终用户可以使用他们在第一个实例中用于构建数据模型的相同术语和概念来自由定义查询。报告的行为本质上是通过导航这些定义来计算数据集,并将结果传递给传统的报告编写工具,就好像它是关系数据一样。
这种方法的优点之一是,将 EAV 模型转换为用户可以使用的模型的相同机制可以重复使用并应用于报告功能。