如何克服EAV数据库报告中的缺点?

8
Entity-Attribute-Value(实体-属性-值)数据库设计在SQL中的主要缺点似乎都与能够高效快速地查询和报告数据有关。我阅读的大部分关于这个主题的信息都警告说由于这些问题以及几乎所有应用程序的查询/报告的普遍性,不要实现EAV。
我目前正在设计一个系统,其中一个实体的字段在设计/编译时未知,并由系统的最终用户定义。对于此要求,EAV似乎是一个很好的选择,但由于我读到的问题,我在实施它时感到犹豫,因为该系统还有一些相当重要的报告要求。我认为我想出了一个解决方法,但我想向SO社区提问。
考虑到典型的规范化数据库(OLTP)仍然不总是运行报告的最佳选项,良好的做法似乎是拥有一个“报告”数据库(OLAP),其中从规范化数据库复制的数据被广泛索引,并可能被去规范化以便更容易查询。是否可以使用相同的思路来解决EAV设计的缺陷?
我看到的主要缺点是将数据从EAV数据库传输到报告中的复杂性,因为您可能需要在报告数据库中更改表格,因为在EAV数据库中定义了新字段。但这几乎是不可能的,并且似乎是EAV设计带来的灵活性所能接受的权衡。如果我使用非SQL数据存储(即CouchDB或类似产品)作为主要数据存储,由于所有标准报告工具都期望针对SQL后端进行查询,因此也存在此缺点。
如果有一个单独的报告数据库用于查询,那么EAV系统的问题是否基本上消失?
编辑:感谢到目前为止的评论。我正在处理的系统中一个重要的事情是,我只是在谈论将EAV用于一个实体,而不是系统中的所有内容。
整个系统的要旨是能够从多个不知道的异构来源获取数据,并对数据进行计算以获得有关特定实体的“最佳已知”数据。因此,我处理的每个“字段”都是多值的,并且还需要跟踪每个历史记录。规范化设计会导致每个字段的1个表格,这使得查询变得有点困难。
以下是我正在查看的表模式和示例数据(显然与我正在处理的内容不同,但我认为它很好地说明了问题)。
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 -
-------------------------------------------------------------------

报告表

Person_Denormalized
----------------------------------------------------------------------------------------
-  Id - Name      - HomeAddress   - HomeAddress_Confidence - HomeAddress_EffectiveDate - 
----------------------------------------------------------------------------------------
- 123 - Joe Smith - 123 Cherry Ln -                  0.713 -                2010-03-26 -
----------------------------------------------------------------------------------------

规范化设计

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

这里的“置信度”字段是使用逻辑生成的,使用SQL很难(如果有可能)表达,因此除了插入新值之外,我最常见的操作是检索关于一个人的所有字段的所有数据,以便为报告表生成记录。在EAV模型中,这实际上更加容易,因为我可以执行单个查询。在规范化设计中,我最终必须针对每个字段执行1个查询,以避免从将它们全部连接起来产生大量笛卡尔积。


将信息存储在 XML 中会更好。因为您可以始终使用 XQuery 而非 SQL 查询它。我们已经成功地在我们的应用程序中实现了这一点。 - Fahad
4个回答

6
在这个方案中,我们首先设计了一个系统,让用户可以存储任何类型的数据,无论其结构如何,也无论未来的使用意图如何。然后,在需要生成报告时,我们必须弄清楚我们拥有什么,以及它与我们需要的内容之间的关系。
由于您明确将问题的性质归因于“处于这个方案中”,所以我真的觉得EAV的问题确实是由EAV本身引起的。
事实上,仔细想想:“允许用户存储任何类型的数据”的等价于允许用户定义他们的关系变量。但是,该系统的哪一部分允许用户对每个属性定义约束条件?糟糕,似乎EAV的人群忽略了数据管理中一个不那么不重要的方面...

你提出了一些好观点,关于EAV你可能是正确的。一个用户能否声明约束来限制另一个用户?如果答案是肯定的,那么“用户定义自己的数据”在一段时间后就会崩溃。如果答案是否定的,那么从整个用户群体的数据中理解意义就需要整合用户没有整合的内容。无论你使用EAV、relvars还是其他什么,我都认为这是一个问题。 - Walter Mitty
我认为澄清涉及的用户性质很重要。“用户定义自己的数据”假设定义EAV模型的人与使用结果系统(即输入和操作数据)的人是同一个人。如果将它们分成3个角色(EAV软件开发人员、EAV数据建模人员、最终用户),那么就更容易理解EAV系统如何在实践中运作良好。简而言之,它们允许定义数据模型以满足不同的问题领域,而不一定是不同的个体最终用户需求。 - Pat
最终用户需求和开发人员的问题域不是同一回事。 - Erwin Smout
@ErwinSmout 如果说一个电子商务应用程序具有EAV产品属性,那么开发人员不会预料到可以添加到商店的所有产品类型。因此,该应用程序为站点所有者提供了创建带有每种类型约束的属性类型的能力,而较低权限的用户输入符合这些约束的数据。 - Damian Yerrick
将“关系变量及其约束条件”替换为“每个属性上的约束条件”的编辑是没有根据和不合理的。我原本就是按照这样写的,那些急于编辑掉它的人应该先对关系数据库中的约束条件主题进行教育。它们的范围远不止“在单个属性上”。 - Erwin Smout
你在评论中提到了一个编辑更改了你的意思,但是你没有将其改回来。 - philipxy

3
EAV的问题并不在于EAV本身,而是由于设计和构建数据库时缺乏了解数据需求以及数据必须具有的逻辑结构。EAV和其他允许用户设计自己的数据系统完全颠覆了这一点。
在这种方案中,我们首先打造一个让用户存储任何类型数据的系统,无论其结构如何,也无视将来的预期用途。然后,在需要生成报告时,我们必须弄清楚我们拥有什么数据,并确定它们与我们所需数据之间的关系。
祝好运。

3
简短回答是,报告数据库是解决从EAV数据模型报告问题的合理方法。
我曾经在一个信息管理解决方案上工作了好几年,该解决方案允许最终用户完全自由地定义自己的数据模型,使用EAV模型存储模式和数据。有趣的是,这个产品提供了元模式对象来满足报告要求(例如,图表提供对象导航,视图执行投影等)。这意味着最终用户可以使用与他们首次构建数据模型时相同的术语和概念来定义查询。报告的实质就是通过导航这些定义计算数据集,并将结果交给传统的报告编写工具,就像它是关系型数据一样。
这种方法的优点之一是,已经用于将EAV模型转换为用户可操作的东西的相同机制可以被重复使用并应用于报告功能。

1

使用EAV查询大型数据库时,我花费了相当多的时间,但并没有遇到任何问题。任何声称从EAV报告数据很困难或不可能的人都有两个问题,要么是他们的EAV系统设计非常糟糕,要么就是他们不知道如何从中查询。一旦你做过几次,从EAV数据库获取可报告的数据非常容易。没有必要使用报告数据库或任何特殊工具,只需要几个好的查询。

如果您正在构建EAV数据库,请花费大量时间进行设计,因为设计将决定应用程序的成败,而且如果设计不良,则尝试修复或处理它将是一场噩梦。


4
我知道这是一个旧答案,但你有没有一些示范正常且可参数化的查询语句?我需要查询一个EAV数据库,看看有多少实体共享各种属性值。在我看来这一点都不容易... - IronicMuffin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接