代码之家  ›  专栏  ›  技术社区  ›  Jan Kronquist

何时不使用代理主键?

  •  9
  • Jan Kronquist  · 技术社区  · 15 年前

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

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

    一般来说,当不应该使用代理键时,有哪些例外情况?

    6 回复  |  直到 6 年前
        1
  •  21
  •   MarioDS    6 年前

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

    • 你的天然钥匙 必须 绝对地,积极地,不允许例外, 独特的 (名字、社会保险号码等似乎都是独一无二的,但事实并非如此)

    • 您的自然键应该和in t一样小,例如大小不超过4个字节(不要对pk使用varchar(50),尤其不要对SQL Server中的集群键使用varchar(50))。

    • 你的天然钥匙应该是稳定的,例如永不改变(好吧,根据国际标准化组织的国家代码,这几乎是一个给定的-除非像南斯拉夫或苏联这样的国家崩溃,或像两个德国那样的国家联合起来-但这是非常罕见的)

    如果满足这些条件,您可以将自然密钥视为您的pk—但这应该是所有表中的2%例外—而不是规范。

        2
  •  3
  •   Lazarus    15 年前

    我不确定当代理键时是否有例外情况 不应该 被使用。我认为,当应用于您描述的系统时,代理键的性质(通常是为了使引用具有全局唯一性)尤其相关。

    虽然您提到的每个卫星主键在其各自的范围内可能都是唯一的,但您不能真正保证它们在整个互连环境范围内保持唯一性,特别是在其扩展的情况下。我怀疑最初的设计师不是在试图证明他们的系统的未来,就是在追随他们所学的最新潮流;)

        3
  •  2
  •   culebrón    15 年前

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

    • 当您看到它们时,它们是有意义的(仅代理键对用户来说没有任何意义)。这对于经常需要使用原始数据库输出的数据库开发人员和维护人员很重要)
    • 较少的连接(通常只需要国家代码,它们已经在其他表中了。如果使用代理键,则需要加入查阅表格)

    自然键的缺点是它们与信息逻辑相关联,如果它发生变化(有时会发生),您需要修改很多表,基本上需要对数据库的一个重要部分进行大修。

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

        4
  •  2
  •   andrew cooke    15 年前

    关于这个问题有一个长期的争论。如果你用谷歌搜索“代理V自然键”,你会得到很多链接。所以我怀疑你会得到一场辩论而不是一个明确的答案。

    this article :

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

        5
  •  0
  •   HLGEM    15 年前

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

        6
  •  0
  •   Walter Mitty    15 年前

    当自然密钥真正可信时,使用自然密钥进行标识是一个好主意。请参阅Marc_的回复,了解一些无法信任自然密钥的情况。不要太担心效率。即使是像VIN(车辆识别号)这样的长的东西也不会把数据库拖得很慢。如果你认为会的话,做一些测试,意识到效率不是线性的。

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

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

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