单个表与两个一对一相关表的性能



假设我们要在关系数据库中存储以下数据:CountryNameCapitalCityNameCapitalCityPostCode。假设一个城市只有一个邮政编码。我们可以以一种简单的方式在一个表中实现它:

Countries
[PK]CountryId, CountryName, CapitalCityName, CapitalCityPostCode

或者我们可以以更规范化的方式将其排列成 2:1 关系的表:

Coutries  
[PK]CountryId, CountryName, [FK]CapitalCityId

CapitalCities
[PK]CapitalCityId, CapitalCityName, CapitalCityPostCode, [FK]CountryId

这将如何影响性能?例如 - 如果我们需要列出所有国家/地区的首都名称,在第一种情况下会快得多吗?我需要多少条记录/列才能看到差异?

显然,你可以看到第一个不是第三个范式。在性能方面,即使处理 10 和 100 的数百万条记录,正确规范化的表也将与第一个示例中的平面表相提并论。虽然平面文件总是会稍微快一些,但如果正确相关,数量微不足道。第一个问题随着时间的推移变成了可扩展性。如果需要增长,您将放弃略微提高的性能,以获得不稳定的基础

这充其量只是一个边际差异。单表总是有一点优势;当您处理数亿条记录+时,这一点会变得更加明显。但是有一些方法可以通过将表划分为相关的块来解决这个问题,这样引擎就可以多线程收集结果并根据连接和过滤条件消除大量不需要的记录。

与任何其他发展一样,没有一颗银弹。规则总是有例外;每个问题的背景都很重要。然而,广义的刷子方法说,正常化,除非你知道永远不会有增长。(永远不会很久! 但是,也许该系统具有已知的保质期,并且永远不会实现如此长期的存在。)

在上面的示例中,对于国家/地区和首都城市的表格,规范化不是很有帮助。一对一的关系不会在读取和更新数据时造成任何重复或复杂化。如果数据需要国家和城市等表格,国家/地区将首都城市作为城市的 fk,这将很有帮助。 从两个表读取需要联接,这肯定比从单个表读取慢(不是很大)。对于数百条记录,看到的差异将是 10 到 15 毫秒。

通常,如果存在一对一的对应关系,则将数据拆分为两个表没有任何好处。如果没有冗余,则不会"规范化"数据。如果您需要按城市搜索,只需指定为"首都城市名称"列编制索引即可。您仍将获得搜索性能,并消除必须联接两个表以进行查询的开销。

另一方面,如果每个城市都有许多邮政编码(非常常见),则需要一个单独的表来规范化数据并提供每个城市(或特定邮政编码的城市)的邮政编码列表。但这带来了一个新问题:邮政编码可能不是唯一的:相同的代码可能在多个国家重复,甚至存在"双城"共享一个共同邮政编码的情况。但这是一个需要另一个讨论的问题。

最新更新