在完全规范化的关系数据库中存储图形

时间:2010-10-16 21:42:18

标签: database-design language-agnostic data-structures graph relational-database

目标

找一个完美的,灵活的架构,用于在关系数据库中存储多种不同类型的对象


问题

EAV是RDBMS正常限制的解决方法。

如果你要规范化EAV架构,那就太丑了。


如果EAV正常化,那将是丑陋的。

我们传统上手动维护这些架构的事实是否限制了它们的复杂性和功能?

但如果以编程方式维护和查询,那有什么关系呢?


图表

如果n个不同的表中有n个不同的实体,为什么不让您的代码生成n(n+1)/2个链接表以及它们之间的查询?这不会导致规范化架构中的真实图形吗?

在高度相互关联的数据库中,边缘总是比顶点多得多。为什么不专注于创建正确的,规范化的Verticle(n实体表)并让我们的代码维护边缘(n^x链接表)?


结论

系统可以规范化EAV并维护最终的复杂架构吗?

复杂图表是否可以存储在关系数据库中(并保持真实)?

我确信此前已经完成,但我从未见过它。我错过了什么?


示例问题

存储印刷品及其书目数据

  • 许多属性,可能不只是字符串而是整个对象。
  • 在图书馆世界中,没有简单(和关系)架构可以无损地存储数据而无需极其复杂的架构。
  • 许多不同类型的关联和关联的对象
    • 及其相关属性(可能会有很大差异)。
    • 他们之间有许多不同类型的关系。

问题

你想解决什么问题?
-Piet

我正在寻找关系数据库系统中EAV,图形和多态关系的规范化解决方案。

我不愿意成为那些在投入生产后必须理解或维护它的人。
-Andrew

这种“传统维护”正是我所说的应该是自动化的。是不是很笨拙的工作?

4 个答案:

答案 0 :(得分:5)

由于您正在编辑问题,因此必须处于活动状态。

是的,为了您描述的目的和用途,有更好的方法来设计它。

第一个问题是EAV,通常执行得非常糟糕。更准确地说,EAV人群,因此文献质量不高,标准不能保持,因此关系数据库的基本完整性和质量丢失了。这导致了许多记录良好的问题。

你应该考虑适当的学术派生的替代方案。这保留了完整的关系完整性和功能。它被称为第六范式。 EAV实际上是6NF的一个子集,没有完全理解;更常见的是6NF的再现。

正确实施的6NF特别快,因为它存储的是列,而不是行。因此,您可以以这种方式映射数据(图形系列,数据点),以便获得平坦的高速,而不管用于访问图形的向量。 (您可以将重复消除到比5NF更高的顺序,但这是高级用法。)

“高度相互关联”根本不是问题。这就是关系数据库的本质。这里需要注意的是,它必须是真正的标准化,而不是一组不连贯的平面文件。

自动化或代码生成不是问题。当然,如果你想要质量和可维护性,你需要扩展SQL目录,并确保它是由表驱动的。

我对这些问题的回答提供了对该主题的全面处理。由于提出的背景和论点,最后一个特别长 EAV-6NF Answer One
EAV-6NF Answer Two
EAV-6NF Answer Three

这个也是值得的:
Schema-Related Problem

答案 1 :(得分:4)

您的想法肯定会创建一个完全灵活的架构,可以表示任何类型的对象图。我不愿意成为那些在投入生产后必须理解或维护它的人。

精心设计的数据模式的一个好处是约束。我不只是引用您可以定义的物理列约束,而是指整体结构所施加的约束。有一组固定的显式关系,这提供了明确定义的路径。

在您的方案中,从一个实体到另一个实体总会存在大量路径。怎么会有人知道哪条路是“正确的”路径。 “正确”路径将只是“开发人员选择填充的一组关系”。

想象一下拥有这些关系的数据库。

客户< ===>发票< ===> InvoiceLineItem< ====>产品

如果我正在看这个,有人问我:“给我一个客户列表,并为每个客户列出他们购买的产品列表”,我知道如何编写查询。

但是,如果这是一个图形,其中所有内容都指向其他所有内容,我将如何知道哪条路径是“正确”路径。它是“Customer_Product”关系,“Customer_Invoice_Line_Item”到“Customer_Product”,或“Customer_Invoice”到“Invoice_Product”,或“Customer”到“Invoice”到“Invoice_Line_Item”到“SomeOtherTableIHaven'tEvenLookedAtYet”到“Product”?答案可能是“它应该是显而易见的”,但只有一个开发人员才能明白这一点。

答案 2 :(得分:3)

  

为什么不让代码生成   n(n + 1)/ 2“链接”表和查询   他们之间?

每当我在计算机科学中看到答案出现“关于n平方”时,我立即认为答案是错误的。 : - )

但更现实的是,当“n”变得适中时,链接表的数量变得非常庞大,非常非常快。这么多,以至于你不能说这种方法可以代表一个通用的解决方案,IMO。

但这是我真正的反对意见 - 您提出的方法不是一个可行的工程解决方案。工程学就是在做出权衡,而这种方法为了一般性而交易很多。例如,通过在经过验证的“传统”数据库设计中使用您的方法,您就失去了这些:

  • 你失去了拥有可发现模式的能力 - 表格的数量如此迅速地失控,任何看着你的桌面设计的人都无法知道这些关系是什么。
  • 除了最基本的引用类型之外,数据库几乎不能强制执行任何数据完整性 - 使用数据库的所有代码必须小心不要违反规则,或者您有数据腐败。
  • 您最终可能拥有大量的表格,这些表格模拟了您的业务领域中并不存在的关系。当您使用“链接”表时,您实际上是在建模多对多关系,这种关系在现实世界中可能存在也可能不存在。
  • 您可能会失去巨大的速度,并且在使用的存储空间方面会受到很大的惩罚。通过直接引用“子”实体中的“父”实体来建模1:N关系的效率要高得多。

答案 3 :(得分:2)

这完全取决于图表的定义。

在关系数据库或其他方面存储图形的唯一“真实”方式是简单的adjacency list(或其变体之一)。其他一切都是这种技术的衍生,专业化或优化,并取决于对问题领域的了解。

您在问题中描述的方法实质上是将此通用邻接列表重新规范或重新规范化为多个“类型”邻接列表(或链接表),这可能是也可能不合适,具体取决于您的问题。

  

我确信此前已经完成,但我从未见过它。我错过了什么?

你可能没有遗漏任何东西:实际上极少需要存储这样的通用图表。你想解决什么问题?

附录

  

在高度相互关联的数据库中,总是会有比指数多的指数边缘。为什么不专注于创建正确的标准化Verticle(表)并让我们的代码保持边缘?

我认为这比你想象的要常见得多。我主要熟悉Python,但是所有可用的主要ORM / RDBMS工具包(SQLAlchemy,Django,SQLObject,...)都支持自动维护多对多链接表作为标准功能。