2009-11-11 69 views
8

我有一个只包含一个单柱和很少的行,往往只是在另一个系统中定义的东西的ID多个数据库表。这些表然后用其他表中的外键引用。例如,一个表格包含国家代码(SE,DK,US等)。所有值始终是唯一的自然键,并且在其他(传统)系统中用作主键。何时不使用代理主键?

看来真的不必引入新的代理键这些表,或?

一般来说,有什么特殊情况时,不应该使用代理键?

回答

20

我想说以下条件必须满足:

  • 你自然的关键绝对,肯定,没有例外允许的,独特(如姓名的事情,社会保障号码等通常似乎是唯一的 - 但真的没有)

  • 你自然键应尽可能小INT,例如不要超过4个字节的大小(不要使用VARCHAR(50)作为你的PK,尤其是不要使用SQL Server中的集群密钥!)

  • 你的自然键应该是稳定的,例如,永远不会改变(OK,符合ISO国家代码,这几乎是一个给定的 - 除非像南斯拉夫和苏联崩溃,或国家其他类似两两德统一 - 不过这也够难得)

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

+1

这些国家的崩溃和联合并不是这个关键变革本身的好例子;当一个实体被拆分成许多或多个实体合并 - 这将是一个相当大的问题,无论这些实体如何被识别。仍然,+1非常好(读:非常严格:)自然键的标准。但我个人认为2%是高估的。 :) – Yarik 2011-10-26 01:04:22

2

自然键(在你的情况下国家代码)更好,因为

  • 他们做出感觉,当你看到他们(代理键单独意味着什么给用户。这是DB开发者和维护者谁重要常常需要使用原始数据库输出)
  • 减少联接(通常只需要国家代码,而且它们已经在其他表中,如果使用代理键,则需要加入查询表)

自然密钥的缺点是第在他们被绑定到信息逻辑,并且如果它改变(有时发生),你需要改变很多表,基本上检修大部分数据库。

所以,如果在你的数据库的逻辑并不多年的变化,使用自然键。

+1

绝对不能将代用键呈现给用户,他们正在用于关联数据。我通常会向用户展示主键(除非他们是自然键,在这种情况下,它们被表示为“键”而不是数据本身)。 – Lazarus 2009-11-11 10:08:49

+0

我已经加入到我的回复中,认为这对发展有利。通常,您有一个表的文本转储,或者在另一个非IDEish环境中工作,并且无法查找参考表。在这种情况下,代理键会显着减慢工作速度。 – 2009-11-11 10:11:46

+0

的确如此,除非代理人是记录的一部分(并且被适当地编入索引),那么随着对数据的需求增长,链接表或任何其他方法的开销可能变得很重要。 – Lazarus 2009-11-11 11:14:56

3

我不确定在使用代理键时不应使用。我认为,将代用关键字的性质(通常是全局唯一的参考)与应用于您描述的系统时特别相关。

虽然每个你提到的可能是他们自己的范围内是唯一的卫星主键,你真的不能保证他们将在您的互联环境的整个范围内保持唯一,尤其是当它展开。我怀疑原来的设计师们要么试图面向未来的系统或骑他们会了解到最新的时尚;)

+2

一个自然钥匙也是全球唯一的,否则它不会是一个自然钥匙。 如果你的意思是代理键在整个数据库中是唯一的,那么你是否说你使用一个单独的计数器共享所有表? – 2009-11-11 10:18:23

+0

如果自然键是全局唯一的,那么根本就不需要替代键。自然键在它们被选择的范围内倾向于是唯一的,但通常不会超出。当在像企业这样的环境中工作时,可能会有许多类似的系统随着时间的推移而创建(并且通过公司购买获得),通过改变公司中的元素,您经常会发现自然键不是唯一的,或者同样不好,单个目标的多个键。 – Lazarus 2009-11-11 11:12:49

+0

我应该补充说,我非常想用数据仓库的方式。为了在系统之间交换数据,我倾向于在中间使用一个网关,并且考虑到性能的提升,以便将来可以进行扩展。 – Lazarus 2009-11-11 11:20:41

2

关于这方面的争论一直存在。如果你是谷歌的“代理v自然键”,你会得到很多链接。所以我怀疑你会在这里得到一个辩论而不是一个明确的答案。

this article

数据建模(这个讨论中,我包括任何人谁设计的表的数据库)被划分在这个问题上:一些建模发誓代理键;其他人会在他们使用除自然键之外的任何东西之前死亡在数据建模和数据库设计方面的文献搜索除了在数据仓库舞台上都不支持任何一方,其中代理键是维度表和事实表的唯一选择。

+0

“......其他人会在他们使用除自然键之外的任何东西之前死亡......”Well说。也许其中许多人已经死亡或辞职。这将解释代孕关键阵营的流行。 – Yarik 2011-10-26 01:17:46

0

除了marc_s所说的内容之外,通常在链表中不需要一个surrgogate键,该链表是包含仅用于创建多对多关系的两个不同主键的表。通常,这两个字段上的复合键在这里工作正常。这是我提出组合键的次数之一,通常我更喜欢组合键上的代理键和唯一索引。

0

只要真正可以信任自然键,使用自然键进行标识就是一个好主意。有些情况下自然密钥不可信,请参阅Marc_S响应。不要太担心效率。即使像VIN(车辆识别号码)这样长的东西也不会拖拉你的数据库。如果你认为它会,做一些测试,意识到效率不会线性缩放。

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

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

如果上述选择导致性能下降,有时可以通过创建一些额外的索引来弥补。这取决于你在处理数据。