Database design 何时不使用代理主键?

Database design 何时不使用代理主键?,database-design,primary-key,Database Design,Primary Key,我有几个数据库表,它们只包含一列和很少的行,通常只是另一个系统中定义的某个对象的ID。然后使用其他表中的外键引用这些表。例如,一个表包含国家代码(SE、DK、US等)。所有值都始终是唯一的自然键,并在其他(遗留)系统中用作主键 似乎真的没有必要为这些表引入新的代理键,或者 一般来说,不应使用代理密钥的例外情况有哪些?自然密钥(您的国家/地区代码)更好,因为 当您看到它们时,它们是有意义的(仅代理键对用户来说并不意味着什么。这对于经常需要处理原始数据库输出的数据库开发人员和维护人员来说很重要)

我有几个数据库表,它们只包含一列和很少的行,通常只是另一个系统中定义的某个对象的ID。然后使用其他表中的外键引用这些表。例如,一个表包含国家代码(SE、DK、US等)。所有值都始终是唯一的自然键,并在其他(遗留)系统中用作主键

似乎真的没有必要为这些表引入新的代理键,或者

一般来说,不应使用代理密钥的例外情况有哪些?

自然密钥(您的国家/地区代码)更好,因为

  • 当您看到它们时,它们是有意义的(仅代理键对用户来说并不意味着什么。这对于经常需要处理原始数据库输出的数据库开发人员和维护人员来说很重要)
  • 较少的联接(通常只需要国家代码,并且它们已经在其他表中。如果使用代理键,则需要联接查找表)
自然键的缺点是它们与信息逻辑相关联,如果它发生了变化(有时会发生),您需要更改许多表,基本上是对数据库的重要部分进行大修


因此,如果数据库中的逻辑多年没有改变,请使用自然键。

我不确定是否存在不应使用代理键的例外情况。我认为,代理密钥的性质,通常是使引用全局唯一,在应用于您描述的系统时尤其相关


虽然您提到的每个卫星主键在其各自的作用域内可能都是唯一的,但您不能真正保证它们在您的互联环境的整个作用域内都是唯一的,尤其是在其扩展的情况下。我怀疑最初的设计师不是在试图证明他们的系统的未来性,就是在利用他们学到的最新时尚;)

我认为必须满足以下标准:

  • 您的自然密钥必须绝对、积极、不允许有任何例外,唯一(姓名、社会保险号码等通常看起来是唯一的,但实际上并非如此)

  • 您的自然密钥应该与INT一样小,例如大小不超过4个字节(不要将VARCHAR(50)用于PK,尤其不要用于SQL Server中的群集密钥!)

  • 您的自然钥匙应该是稳定的,例如永不更改(好吧,对于ISO国家代码,这几乎是给定的-除非像南斯拉夫或苏联这样的国家崩溃,或者像两个德国那样的其他国家联合起来-但这已经够少了)


如果满足这些条件,你可以考虑一个自然键作为你的PK——但这应该是你所有表中的2%个例外,而不是标准。

< P>这是一个长期的争论。如果你在谷歌上搜索“代理v自然键”,你会得到很多链接。所以我怀疑你会得到一个辩论,而不是一个明确的答案

发件人:

数据建模者(在本次讨论中,我包括为数据库设计表的任何人)在这个问题上存在分歧:一些建模者发誓使用代理键;其他人会在使用自然钥匙之前死去。搜索有关数据建模和数据库设计的文献,除了在数据仓库领域外,任何一方都不支持,在数据仓库领域,维度表和事实表都只能选择代理键


除了marc_s所说的之外,在链接表中通常不需要surrgogate键,该表只包含两个不同的主键,用于创建多对多关系。通常,这两个字段上的复合键在这里都可以正常工作。这是我为数不多的几次建议使用复合密钥之一,一般来说,我更喜欢使用代理密钥和复合密钥上的唯一索引。

只要可以真正信任自然密钥,就最好使用自然密钥进行标识。参见Marc_的回复,了解一些自然密钥不可信的情况。不要太担心效率。即使是像VIN(车辆识别号)这样的长代码也不会让您的数据库太慢。如果你认为会的话,做一些测试,意识到效率不是线性扩展的

声明主键的主要原因是防止表滑出第一个正常形式,从而不再表示关系。使用自动递增的代理项可能会导致两行具有不同id字段,但在其他方面相同。这将给您带来一些与非第一范式的数据相关的问题。用户将无法提供帮助,因为他们看不到id字段

如果一个表的行可以由两个或多个外键的组合来确定,那么您拥有的就是一个关系表,有时称为链接表或连接表。通常最好声明一个由所有需要的外键组成的复合主键


如果上述选择导致执行缓慢,有时可以通过创建一些额外的索引来补救。这取决于您对数据所做的操作。

当然,代理键永远不应该呈现给用户,它们被用来关联数据。我通常会将主键呈现给用户(除非它们是自然键,在这种情况下,它们呈现为“键”,而不是数据本身)。我在回答中补充说,这是开发的一个优势。通常,您有一个表的文本转储,或者在另一个非IDEish环境中工作,并且无法查找引用表。在这种情况下,代理键会显著降低工作速度。这是事实,除非代理项是记录的一部分(并进行了适当的索引),否则,随着数据需求的增长,链接表或任何其他方法的开销可能会变得非常大。查看我的第一条注释,我已经成功地完成了