SQL:主键列。人工“Id”列与“Natural”列[重复]
Posted
技术标签:
【中文标题】SQL:主键列。人工“Id”列与“Natural”列[重复]【英文标题】:SQL: Primary key column. Artificial "Id" column vs "Natural" columns [duplicate] 【发布时间】:2011-02-10 17:06:04 【问题描述】:可能重复:Relational database design question - Surrogate-key or Natural-key?
当我创建关系表时,很容易选择主键列,即值是唯一的列。但出于优化和统一的目的,我每次都创建人工 ID 列。如果有一列(或列组合)应该是唯一的,我会为此创建唯一索引,而不是将它们标记为(复合)主键列。
总是选择人工“Id”列+索引而不是主键的自然列真的是一种好习惯吗?
【问题讨论】:
有时很难找到答案——它们都很好:) 是的,我同意。 =) SO的工作方式是通过投票和接受的答案。做一个好的法官,选择一个更完整的。坐在初学者的座位上阅读它们,并尝试从哪个答案中找出您学到或本可以学到最多的答案。没有人会生你的气! ;-) 此外,当人们有更好的机会提高声誉时(只有当他们应得的时候),他们会很乐意通过回答您的问题来努力帮助您。保重,有一个美好的白天/黑夜! =) 【参考方案1】:这有点像宗教辩论。我个人的偏好是拥有合成主键而不是自然主键,但双方都有很好的论据。实际上,只要您保持一致和合理,任何一种方法都可以很好地工作。
如果您使用自然键,则两个主要缺点是存在复合键和可变主键值。如果你有复合主键,你显然必须在每个子表中有多个列。当实体之间存在许多关系时,从数据模型的角度来看,这可能会变得笨拙。但它也会让开发查询的人感到悲痛——创建使用 N-1 of N 个连接条件的查询并获得几乎正确的结果非常容易。如果您有自然键,您也不可避免地会遇到自然键值发生变化的情况,然后您必须通过许多不同的实体来影响这种变化——这比更改表中的唯一值要复杂得多。
另一方面,如果您使用合成键,则会通过添加额外的列来浪费空间,增加额外的开销来维护额外的索引,并且会增加获得功能重复结果的风险。很容易忘记在业务键上创建唯一约束,或者看到组合中有一个非唯一索引并假设它是一个唯一索引。实际上,几天前我刚刚被这个特殊的失败所困扰——我已经索引了复合自然键(使用非唯一索引)而不是创建唯一约束。愚蠢的错误,但相对容易犯。
从查询编写和命名约定的角度来看,我也倾向于使用合成键,因为很高兴知道当您连接表时 A 的主键将是 A_ID 而 B 的主键将成为 B_ID。这比试图记住 A 的主键是 A_NAME 和 A_REVISION_NUMBER 的组合并且 B 的主键是 B_CODE 更能自我记录。
【讨论】:
【参考方案2】:通过 PRIMARY KEY 约束强制执行的键和通过 UNIQUE 约束强制执行的键之间几乎没有区别。重要的是您从数据完整性的角度强制执行所有必要的密钥。通常这意味着每个表至少一个“自然”键(向数据的用户/消费者公开并用于识别有关话语领域的事实的键)。
您可能还希望创建“技术”键来支持应用程序和数据库功能,而不是最终用户(通常称为代理键)。然而,这应该是次要的考虑因素。为了简单起见(通常也是为了性能),通常只在您确定了对它们的特殊需求而不是之前创建代理键时才有意义。
【讨论】:
【参考方案3】:这取决于您的自然列。如果它们很小且稳步增长,那么它们是主键的良好候选者。
小 - 键越小,单行可以获取的值越多,索引扫描的速度也会越快 稳步增长 - 随着表的增长产生更少的索引重组,从而提高了性能。【讨论】:
【参考方案4】:我的偏好是始终使用人工钥匙。
首先它是一致的。任何在您的应用程序上工作的人都知道有一个密钥,他们可以对其进行假设。这样更容易理解和维护。
我还看到了自然键(也就是来自 HR 系统的用于识别员工的字符串)在应用程序的生命周期中必须更改的场景。如果您有一个将自然 ID 链接到您的员工记录的人工密钥,那么您只需在一个表中更改该自然 ID。但是,如果该自然 id 是主键,并且您将它作为外键复制到许多其他表中,那么您的手就会一团糟。
【讨论】:
【参考方案5】:以我的拙见,如果我正确理解你的意思,最好有一个人造的身份。
有些人会使用,例如,业务重要的唯一值作为他们的表 ID,我已经在 MSDN 上阅读过,甚至在 NHibernate 官方文档中,首选唯一的业务无意义值(人工 ID),尽管你想要为该值创建索引以供将来参考。所以,公司改名的那一天,系统还是可以正常运行的。
【讨论】:
【参考方案6】:是的,是的。如果不出意外,人工主键最重要的属性之一是不透明度,这意味着人工主键不反映自身以外的任何信息;如果您使用自然行内容作为键,您最终会将这些信息暴露给 Web 界面之类的东西,这在所有原则上都是一个糟糕的想法。
【讨论】:
公开有意义的键并不是一个糟糕的主意!用户通常需要这些自然键来在外部世界中识别数据库应该记录的事物。在用户界面中公开密钥只是准确表示信息和业务规则的必然结果。以上是关于SQL:主键列。人工“Id”列与“Natural”列[重复]的主要内容,如果未能解决你的问题,请参考以下文章