外键 - 使用代理或自然键的链接?

Chr*_*s J 15 foreign-key database-design surrogate-key natural-key

表之间的外键是否应该链接到自然键或代理键是否有最佳实践?我真正找到的唯一讨论(除非我的 google-fu 缺失)是Jack Douglas 在这个问题中的回答,他的推理对我来说似乎是合理的。我知道除了规则改变之外的讨论,但这在任何情况下都需要考虑。

提出这个问题的主要原因是我有一个遗留应用程序,它使用带有自然键的 FK,但是开发人员强烈推动转向 OR/M(在我们的例子中是 NHibernate),并且一个 fork 已经产生了一些破坏性更改,因此我希望使用自然键将它们推回正轨,或者移动旧应用程序以使用 FK 的代理键。我的直觉告诉我要恢复原始的 FK,但老实说,我不确定这是否真的是正确的道路。

我们的大多数表都已经定义了代理键和自然键(尽管是唯一约束和 PK),因此在这种情况下,必须添加额外的列对我们来说不是问题。我们使用的是 SQL Server 2008,但我希望这对于任何数据库都足够通用。

Mik*_*ll' 16

SQL 和关系模型都不会受到引用自然键的外键的干扰。事实上,引用自然键通常会显着提高性能。您会惊讶于您需要的信息完全包含在自然键中的频率如此之高;引用该键会将联接交换为更宽的表(从而减少您可以在一页中存储的行数)。

根据定义,您需要的信息总是完全包含在每个“查找”表的自然键中。(术语查找表是非正式的。在关系模型中,所有表都只是表。美国邮政编码表可能具有如下所示的行:{AK, Alaska}, {AL, Alabama}, {AZ, Arizona}等。大多数人会称其为查找表。)

在大型系统上,找到具有多个候选键的表并不罕见。为企业的一部分服务的表引用一个候选键,而为企业的另一部分服务的表引用不同的候选键也很常见。这是关系模型的优势之一,它是 SQL 支持的关系模型的一部分。

当您在也有代理键的表中引用自然键时,您会遇到两个问题。

首先,你会让人们感到惊讶。尽管我通常会为“最小惊喜原则”进行强烈游说,但这是一种我不介意让人们感到惊讶的情况。当问题是开发人员对外键的逻辑使用感到惊讶时,解决方案是教育,而不是重新设计。

其次,ORM 通常不是围绕关系模型设计的,它们有时包含不反映最佳实践的假设。(事实上​​,它们的设计似乎经常没有数据库专业人员的输入。)在每个表中都需要一个 ID 号是这些假设之一。另一种假设是 ORM 应用程序“拥有”数据库。(因此可以自由地创建、删除和重命名表和列。)

在 30 年的时间里,我曾研究过一个数据库系统,该系统为数百个用至少两种语言编写的应用程序提供数据。该数据库属于企业,而不是 ORM。

引入破坏性更改的分叉应该是一个亮点。

我在我曾经工作过的公司测量了自然键和代理键的性能。有一个临界点,代理键开始优于自然键。(假设没有额外的努力来保持高自然关键性能,例如分区、部分索引、基于函数的索引、额外的表空间、使用固态磁盘等。)根据我对该公司的估计,他们将在大约 2045。同时,它们使用自然键获得更好的性能。

其他相关答案:In Database Schema Confusing


HLG*_*GEM 5

我支持代理键的主要原因是自然键经常会发生变化,这意味着必须更新所有相关表,这会给服务器带来相当大的负载。

此外,在 30 年来,我一直在许多主题上使用各种数据库,真正的自然键通常相当罕见。事情应该是独一无二的 (SSN) 不是,在特定时间唯一的东西以后可能会变得不唯一,而且电子邮件地址和电话号码等某些东西可能是唯一的,但以后可以为不同的人重复使用日期。当然,有些东西根本就没有一个很好的唯一标识符,比如人和公司的名字。

至于通过使用自然键避免连接。是的,这可以加快不需要连接的 select 语句,但它会导致您仍然需要连接的地方变慢,因为 int 连接通常更快。它也可能会减慢插入和删除的速度,并且会在键更改时导致更新性能问题。复杂的查询(无论如何都比较慢)会更慢。因此,简单查询速度更快,但报告和复杂查询以及针对数据库的许多操作可能会更慢。这是一种平衡行为,可能会以一种或另一种方式倾斜,具体取决于查询数据库的方式。

所以没有一个一刀切的答案。这取决于您的数据库以及查询方式以及其中存储的信息类型。您可能需要进行一些测试,以找出在您自己的环境中最有效的方法。