想象一下,在我们的数据模型中,我们有一个实体(一个数据结构),它有可选的部分。我们可以将这些“部件”实现为对其他(子)实体的可空引用。换句话说,主实体的每个实例可能有或没有与其相关联的其他(子)实体的一个实例,而任何子实体的实例只有一个与其相关联的主实体的实例。所以我们有1到0.1的关系。
例如,审计日志记录有公共字段(时间戳、用户、操作)和特定于操作的部分(扩展信息),对于不同的操作可以完全不同。我们可以使用单独的实体来表示每种类型的扩展信息,然后使主实体具有对每种可能类型的扩展信息的可空引用。
我可以看到在关系数据库中实现它的两种方法:
1.主记录中对子实体的可空引用
对于每种类型的子实体,主记录表都有一个字段,将子表(扩展名)表中的记录ID作为外键引用。
这似乎是更简单的选择:要检索相关信息,我们只需遵循直接引用。在SQL查询中,我们将按外键左转联接子表(扩展)表。外键的空值将为所有子表的字段提供空值。
2.儿童实体的记录参考主实体的记录
我们不将任何引用存储在主实体表中。相反,子实体表的每个记录都将主表中的一个记录按ID作为外键引用。在SQL查询中,我们仍然将-join子表留给主表,对于没有对应子记录的所有子表的字段,我们都获得了空值。
???
哪种方法是正确的?第二个似乎是更多的关系,我们不需要在主表中创建额外的字段,但从技术上讲,它可能需要更多的工作才能找到相关的记录,因为我们必须在子表中搜索主ID,而不是遵循直接引用。还是DB引擎对这种连接进行了快速优化,例如使用索引?索引搜索比扫描快,但仍然比直接引用慢。加上索引占用空间。我不知道DB引擎是如何工作的..。或者我只是错过了一些显而易见的东西。我们会非常感谢你的帮助。
更新
在得到下面的答案之后,也有了一些思考,并决定采用第二种方法。除了在接受的答案中所说的(更紧凑,从关系角度更正确,不需要处理NULL)之外,如果我需要删除带有所有相应子记录的主记录,它也给了我很好的使用级联删除的可能性。
发布于 2020-01-22 06:24:49
在这种情况下,我认为“最优”解决方案取决于数据库的工作负载,因为这两种解决方案都有优缺点。
第二个解决方案没有空值,这通常会使查询复杂化(空值还使解决方案对关系模型的纯粹主义者来说“不正确”),但也有其他好处:它需要更少的空间(因此,对于某些类型的操作,这种关系更加紧凑,需要更少的时间来操作)。另一方面,它需要连接来访问详细的数据(因此需要为这些操作增加一个索引)。
第一种解决方案在概念上更简单,在访问详细数据时不需要连接,但需要更多空间,这可以减缓某些类型的操作。
这两种解决方案都适用于实际情况。
我认为,只有知道哪些是必须部署在此类数据库上的应用程序的典型工作负载,才能提供解决这一困境的解决方案:是否更频繁(或必须减少延迟)对其他查询进行某些查询?例如,只看一般数据的查询比需要详细数据的查询使用得更频繁?
最后,如果难以或不可能进行这种“理论”分析,唯一的办法是尝试一种解决办法,但如果性能不令人满意,也准备尝试另一种方法。这可以通过使用视图来完成,例如以这种方式:
。
通过在这两种情况下为视图和基表交换相同的名称,应用程序将只需要一组最小的修改,您可以尝试这两种方法。
https://stackoverflow.com/questions/59851836
复制相似问题