数据库设计中的继承

6

我正在设计一个新的实验室数据库,其中包含许多我的主实体类型。

每个实体的表将保存所有类型的该实体的公共字段(entity_id、created_on、created_by等)。然后,我将使用具体继承(为每个唯一属性集创建单独的表)来存储所有其余字段。

我认为这是处理实验室日常流程中标准数据的最佳设计。但是,我们经常有特殊样本,通常伴随着发起者希望存储的特定值。

问题:如何对特殊(非标准)实体进行建模?

选项1:使用实体-值存储特殊字段
一个表(entity_id、attribute_name、numerical_value)将保存任何特殊实体的所有数据。
+ 较少的表。
- 无法强制要求特定属性。
- 必须转换(透视)行到列,效率低下。

选项2:严格的具体继承。
为每个单独的特殊情况创建单独的表。
+ 符合所有其他规则
- 许多只有几行的表的开销较大。

选项3:具体继承,特殊表位于不同的用户下。
将所有特殊表放在不同的用户下。
+ 保持所有特殊和标准表分开。
+ 更容易在列表中搜索常见的标准表,而无需搜索所有特殊表。
- 许多只有几行的表的开销较大。


1
许多只有几行的表格很可能比实体-值表格表现更好,特别是当它变得很大时。而且它们要容易查询得多。 - HLGEM
5个回答

9

实际上,您所描述的设计(通用表加子类型特定表)称为类表继承

具体表继承将在子类型表中复制所有通用属性,并且您现在没有超类型表。

我强烈反对EAV。 我认为它是SQL反模式。 它可能看起来是一种优雅的解决方案,因为它需要较少的表,但是您将为自己日后带来很多麻烦。 您已经确定了一些缺点,但还有许多其他缺点。 在我看来,只有在绝对创建新表时引入新子类型,或者如果您有无限数量的子类型(例如,用户可以临时定义新属性),才适当地使用EAV。

你有许多子类型,但它们的数量仍然是有限的,因此如果我在做这个项目,我会坚持使用类表继承。每个子类型可能只有少量行,但至少您可以确保每个子类型中的所有行都具有相同的列,您可以使用NOT NULL(如果需要),可以使用SQL数据类型,可以使用引用完整性约束等。从关系的角度来看,它比EAV更好的设计。

还有一个选项你没有提到,叫做序列化LOB。即,在半结构化的自定义属性集合中添加BLOB列。在该列中存储XML、YAML、JSON或您自己的DSL。您将无法轻松地使用SQL解析出该BLOB中的单个属性,您必须将整个BLOB取回到应用程序中,并在代码中提取单个属性。因此,在某些方面它不太方便。但是,如果它满足您对数据的使用,则没有任何问题。


实际上,我的设计是类和具体的混合体。它使用类级别来处理所有类型共有的字段,使用具体级别来处理所有其余字段(其中许多字段对多种类型都是共有的)。 - Steven
我可能没有听懂您说的话,但是听起来您描述的正是类表继承。 - Bill Karwin
我的设计将仅有两个层次。主层次(一个表)包含所有类型通用的字段。第二个层次(多个表)中,每种类型都有一个表格。尽管几种类型可能有一些共同的字段,但我没有第三个(或更高层次),这对于继承完全是类级别所必需的。 - Steven
啊哈,我明白了。在真正的面向对象层次结构中,你应该有超过两个级别,但出于简单起见,你在数据库设计中做出了妥协。现在我明白为什么你认为这是混合的了,谢谢。 - Bill Karwin
如果不断引入新的子类型或者现有的子类型结构经常发生变化,那么类表继承可能不合适。 - hythlodayr

1

我认为这主要取决于你想如何使用这些数据。

首先,我真的看不出选项3比选项2有什么好处。我认为将特殊表格分离到另一个模式中会使你的应用程序更难维护,特别是如果以后发现了“特殊值”之间的共性。

作为另一种选择,我建议: - 将特殊值存储在XML片段(或blob)中。大多数数据库现在都有查询XML结构的能力,因此无需许多额外的表格,您可以保持灵活性,但会稍微影响性能。

如果您将所有特殊值放入一个表中,则会得到一个非常稀疏的表。大多数普通的DBMS不能很好地处理这个问题,但有一些实现专门针对此问题。您可以从中受益。

您经常需要查询键值对吗?如果您基本上通过entry_id访问该表格,那么拥有一个键值表格并不是一个坏设计。在kay列上增加一个额外的索引甚至可能在您需要查询特殊值时帮助您。如果您在数据库之上构建一个应用程序层,则键值表将映射到Map或Hash结构,这也可以轻松使用。

这也取决于您想要存储的不同类型的值。如果有许多不同类型需要轻松访问(而不是序列化/反序列化为XML /字符串),则可能需要将类型存储在单独的列中,但这通常会导致非常复杂的设计。

希望这能有所帮助(尽管只是一点点)。

-Maarten


为什么 Oracle 不能处理稀疏填充的表格?根据这个网站 http://highscalability.com/stack-overflow-architecture ,他们是可以做到的。 - tuinstoel

1

1

Oracle可以很好地处理稀疏填充的表。我认为你可以采用与Salesforce公司类似的方法。他们使用具有许多列的表,在需要时创建列。您可以比eav模型更好地索引这些列。

因此,它是灵活的,但性能优于eav模型。

阅读:Ask Tom 1Ask Tom 2High ScalabiltySalesForce


1

“选项1”模式也被称为“通用关系”。乍一看,它似乎是不进行潜在困难数据建模的捷径。它通过轻松的数据建模来换取不能像在具有多个表的常规数据模型上那样简单地进行选择、更新、删除所需付出的努力。


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