【问题标题】:Relational database design question - Surrogate-key or Natural-key?关系数据库设计问题 - 代理键或自然键?
【发布时间】:2011-04-14 10:43:51
【问题描述】:

哪一个是最佳实践以及为什么

a) 类型表,代理/人工键

外键是从user.typetype.id

b) 类型表,自然键

外键是从user.typetype.typeName

【问题讨论】:

标签: sql database-design data-modeling surrogate-key natural-key


【解决方案1】:

我相信在实践中,使用natural key 很少是最佳选择。我可能会像您的第一个示例一样采用surrogate key 方法。

以下是自然键方法的主要缺点:

  • 您的类型名称可能不正确,或者您可能只是想重命名该类型。要对其进行编辑,您必须更新所有将其用作外键的表。

  • int 字段上的索引将比varchar 字段上的索引更紧凑。

  • 在某些情况下,可能很难拥有unique 自然键,这是必要的,因为它将用作主键。这可能不适用于您的情况。

【讨论】:

  • 感谢您的详细回答,其他答案也很棒
  • 一般来说,最好的解决方案是两者兼有 - 使用代理键来确保引用完整性,并使用自然键(通常是复合键)来强制元组的唯一性。因此,在上面的示例中,type.typename 和 user 中的某些列组合上将存在唯一约束/索引。
【解决方案2】:

第一个更具前瞻性,因为它允许您在不更新整个用户表的情况下更改表示类型的字符串。换句话说,您使用surrogate key,这是为了灵活性而引入的附加不可变标识符。

【讨论】:

    【解决方案3】:

    使用代理键(而不是像名称这样的自然键)的一个很好的理由是,当自然键在唯一性方面并不是一个好的选择时。在我的一生中,我认识不少于 4 个“克里斯·史密斯”。人名不是唯一的。

    【讨论】:

      【解决方案4】:

      我更喜欢使用代理键。人们通常会识别并使用自然密钥,这在一段时间内会很好,直到他们决定要更改值。然后问题就开始了。

      【讨论】:

      • 在正确支持外键语义的数据库中,从一开始就获得正确的模式(在正确的位置更新级联),改变这一点只是棘手的。如果您的数据库不能很好地支持这一点,那么您避免自然键是正确的。
      【解决方案5】:

      您可能应该始终使用 ID 号(这样,如果您更改类型名称,则无需更新用户表)它还可以让您降低数据大小,因为一个充满 INT 的表很多小于一个完整的 45 个字符的 varchars。

      【讨论】:

        【解决方案6】:

        如果 typeName 是自然键,那么它可能是更可取的选项,因为它不需要连接即可获取值。

        您应该只在名称可能更改时才真正使用代理键 (id)。

        【讨论】:

          【解决方案7】:

          也请给我代理键。

          当您需要编写一些代码时,另一个可能会更容易,但最终会更难。过去,我的技术老板决定使用电子邮件地址作为主键是个好主意。不用说,当人们想要更改他们的地址时,它真的很糟糕。

          【讨论】:

            【解决方案8】:

            只要自然键起作用,就使用它们。名称通常不起作用。它们太易变了。

            如果您要发明自己的数据,那么您不妨发明一把合成密钥。如果您正在构建由其他人或其软件提供的数据数据库,请分析源数据以了解他们如何识别需要识别的事物。

            如果他们能够很好地管理数据,他们将拥有适用于重要内容的自然键。对于不重要的东西,适合自己。

            【讨论】:

              【解决方案9】:

              我认为,当您没有任何唯一标识的键的值相关且有意义的唯一标识键作为其主键时,我认为代理键很有帮助......此外,代理键更易于实现且维护开销更少。

              但另一方面,代理键有时会通过加入表格来产生额外费用。 想想“用户”……我有

              UserId varchar(20), ID int, Name varchar(200)
              

              作为表结构。

              现在考虑我想在许多表上跟踪谁在插入记录...如果我使用Id 作为主键,那么[1,2,3,4,5..] 等将在外部表中并且每当我需要知道时谁在插入数据我必须加入用户表,因为1,2,3,4,5,6 毫无意义。但是如果我使用UserId 作为唯一标识的主键,那么在其他外部表上[john, annie, nadia, linda123] 等将被保存,这有时很容易区分和有意义。所以我每次查询时都不需要加入用户表。

              但请注意,它需要一些额外的物理空间,因为 varchar 保存在需要额外字节的外部表中。当然,索引存在显着的性能问题,其中 int 性能优于 varchar

              【讨论】:

                【解决方案10】:

                代理键是自然主键的替代。 它只是可用于表主键的每一行的唯一标识符或数字。 代理主键的唯一要求是它对于表中的每一行都是唯一的。

                这很有用,因为自然主键(即客户表中的客户编号)可以更改,这使得更新更加困难。

                【讨论】:

                • 提出问题 5 年后,并没有添加任何有用的信息。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2011-06-24
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多