何时不应使用身份验证/自动编号字段作为主键?

3
我不相信有什么万能的解决方案,但我非常喜欢使用序列或自动编号身份列作为数据库表的主键列。它们是唯一的,索引效果好,而且我不必担心空值。
另一方面,在某些情况下,如果表中有其他唯一列可以起到同样的作用,它们似乎是多余的。例如,你正在构建一个将9位数字邮政编码映射到城市区域的表。如果你能保证数据格式和值不重复,那么邮政编码字段也可以很好地工作。
总之,我的经验像我们所有人一样是有限的。还有哪些真实世界的例子导致人们选择不使用自动编号列作为表的主键,以及原因是什么?这对我来说是一种"开阔眼界"的事情,我希望能从那些与各种数据库打过交道并有充分理由选择其他方法的人那里学到一些东西。
8个回答

5

在我看来,使用身份列非常重要,因为即使最简单的表在未来可能变得更加重要。

唯一不使用身份列的情况是,我使用GUID代替,在这种情况下,记录可能是在断开连接的客户端上创建的,然后需要与中央系统同步。


就是那种“你永远不知道”的事情让我感到困扰。我不想过度设计数据库(YAGNI),但同时,我也不想在事后再去处理添加自动编号列的麻烦。如果我们的关于“坚如磐石”的主键选择的假设被证明是错误的,并且我们不得不回溯它们,那将是令人不安的。 - Mike Hofer

5

我的经验法则是:“如果在正常使用中要添加记录,则使用自动增量主键;如果是静态表,则使用更加自然的标识符”

换句话说:用户、历史记录、资产等都要用自动增量主键。邮政编码/城市、类型/描述、机器ID通常使用“自然”键。


4
一张链接表可能是由于具有复合键而显然的选择。

1
是的,这些都是让我困惑的表格的典型例子。我发现自己在对它们建模时使用了自动编号列,然后问自己,“为什么?”这两列都是唯一的;它们是外键!添加另一列是多余的! - Mike Hofer

3

我坚信在几乎所有情况下都应该使用技术主键,因此我的答案是……从来不需要。


1
你能澄清一下你所说的“技术主键”是什么意思吗? - Mike Hofer

2

在需要频繁进行数据转储/加载/合并且存在外键关系的情况下,我通常会避免使用自增列(auto_increment)。尝试从使用自增id的相同模式的两个表实例中合并数据是一个可怕的问题。

这种用法对大多数人来说并不常见,但我的工作涉及大量批处理,每个批次都会合并到主数据库中以供后续分析/使用。


我猜在这些情况下,使用UUID作为主键会起到作用。 - Javier

1

我认为唯一需要使用标识列的情况是当用于主键的字段数量很大,或者作为主键的字段非常大(例如20个字符的字符串)。在所有其他情况下,我更喜欢不使用它们。

关于标识符的问题,没有人提到的是当数据发生变化时会发生什么。由于键仅基于记录添加的时间,因此在灾难事件后重新加载数据到表中是一个真正的问题。现在,数据库管理系统应该帮助您防止截断表或切换主键值...应该。事情发生了,表被损坏,或者数据库更新遇到问题。对于标识主键,突然之间你就会陷入困境,试图弄清楚哪个标识值与哪一行相对应....等等,除非你不能,因为标识值对于数据没有意义。对于少量条目,您可能还可以,但是当您开始拥有数百万个值的较大表格时(我们的表格在这种情况下略高于1100万),这将迅速成为一个问题。每个人都说,“那是最坏的情况,永远不会发生。”直到它发生了。


1
你在用户表上的主键会是什么?他们的用户ID吗?我希望没有人结婚并想要更改他们的用户ID,否则更改所有外键到新的用户ID将会非常麻烦! - KM.
  1. 级联更新
  2. 如果您的主键发生更改,那么您选择的主键可能不太好。
  3. 是的,它应该是用户ID。简单的解决方案是不允许人们更改它。你真的见过多少次用户ID更改?婚姻与此无关。这可能会存在安全风险,所以不要允许更改。如果您真的担心更改用户ID,则应停用该帐户并创建一个新帐户。
- kemiller2002
@Kevin,在我们的系统中,人们已经更改了使用的ID。你告诉那位离婚女士,她必须保留她的旧ID,我不会同意更改。他们不希望他们之前/当前的所有工作与他们无关,这种情况会在新ID下发生。 - KM.
我没有问题做到这一点。我的工作是保护高度敏感的信息。这可能听起来很冷酷,但因为他们想要更改用户名而产生不良情绪的人并不是我优先考虑的对象。更改用户名只是潜在攻击者掩盖入侵系统的另一种途径和方法。 - kemiller2002
用户名称或ID的显示值不是关键,这就是我使用身份标识的原因。 - KM.
显示剩余6条评论

1

我没有使用自动编号字段的一个领域是,在定义星型模式的DateDimension表时。在这种情况下,我使用了一个以yyyymmdd格式表示日期的整数。这样可以实现快速连接中央事实表和DateDimension(与自动编号ID列一样)。然而……

DateDimension表包含其他日期表示(例如smalldatetime列、dayOfWeek列等)。如果用户只想要yyyy-mm-dd格式的日期,则不需要连接,因为中央事实表中的日期维度键已经存储了这些信息。

总的来说,我不太喜欢包含业务信息的键。通常,在设计架构时对主键做出的假设随着时间的推移不再成立,你会变得卡住。但在这种情况下,我相当确定日期不会发生改变!


0
Iain Hoult、Javier和TK所表达的原则有一个例外,那就是将员工号码或“徽章号码”用作人事表的主键。在这种情况下,只有因为我们已经将员工的主键交给了他的人事记录,所以主键才可以被称为“有意义的键”。
-Al.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接