每个 MySQL 表都应该有一个自动递增的主键吗?

Posted

技术标签:

【中文标题】每个 MySQL 表都应该有一个自动递增的主键吗?【英文标题】:Should every MySQL table have an auto-incremented primary key? 【发布时间】:2011-11-12 13:14:06 【问题描述】: 我了解主键的价值。 我了解索引的价值。

是否应该每个 mysql 表都有一个自动递增的主键(最好是 INT 字段类型)?

更新

@Raj More 的回答似乎是最有效的。然而,当我想到这个问题时,这个自动递增的主键 ID 将如何与其他表相关联。例如:

表 1

ID  |   firstname  |   lastname | email
----------------------------------------
1   |    john      |   doe      | 1@email.com
2   |    sarah     |   stow     | 2@email.com
3   |    mike      |   bro      | 3@email.com

表 2

ID  | memberid |    display      |    address
--------------------------------------------
1   |    1     | funtime zone    |   123 street
2   |    3     | silly place llc |  944 villa dr 

在上面的示例中,消费者可能会来到网站并选择注册免费产品/服务。如果消费者选择,他们可以提供额外的信息(存储在表 2 中)以进行额外的邮寄等。我看到的问题是这些表与“主键自动递增字段”的关系。在表 2 中,“memberid”与表 1 的 ID 相关,但这并不是“非常”清楚的。放入表 2 的任何新信息都将递增 1,但并非所有消费者都会选择参与表 2 所需的数据。

【问题讨论】:

Surrogate vs. natural/business keys的可能重复 @ypercube - 真的吗?您将其列为另一个答案中给出的示例的可能重复项?第一个评论者进行了类似的评估,投了赞成票,然后删除了他自己的评论。 为什么听起来很奇怪? ("完全重复:这个问题与之前关于该主题的问题所涵盖的内容完全相同;它的答案可能会与另一个相同的问题合并。") 我的回答很快就会被删除。我的观点是,这两种选择都有很多优点和缺点(在其他类似问题中讨论过)。说“我喜欢这个,我选择是的,阅读这个”并不是一个真正的答案。 您的更新是表 (2)(与另一个表具有 1:1 关系)的一个很好的例子,其中自动递增的主键是无用的。 memberid 可以是 PK(不是自动递增,因为它也是 table1 的 FK)。 【参考方案1】:

我不是代理键的忠实粉丝。我还没有看到我更愿意为数据库的每个表使用一个的场景。

我会说

阅读这个答案:surrogate-vs-natural-business-keys


以上内容可能被视为讽刺或煽动性(尽管点赞数出奇地多),因此将其删除。

在一般情况下,有很多关于代理和自然键的问题和答案,所以我觉得这个问题更像是重复。我的观点是代理键很好而且非常有用,主要是因为自然键可以在连接表链的低端导致非常大的主键 - 许多 RDBMS 处理不好,聚集索引变大等. 但是说“每个 MySQL 表都应该有一个自动递增的主键”是一个非常绝对的陈述,我认为在某些情况下他们真的提供很少或根本没有提供。

由于 OP 更新了问题,我将尝试对该特定主题发表评论。

我认为这正是自动递增主键不仅无用而且增加了负值的情况。假设table1table21:1 关系中,memberid 可以是Primary KeyForeign Keytable1

添加一个自动递增的 id 列会添加一个索引,如果它是一个集群索引(如 InnoDB PK 索引),则会增加 memberid 索引的大小。更重要的是,如果您有这样一个自动递增的 id,则必须使用此 id(与表 2 的关系 1:n 中的表的 JOIN)和一些使用 memberid1:ntable1 关系中的表的 JOIN)。如果你只有 memberid 这两种类型的 JOIN 都可以 使用memberid 完成。

【讨论】:

我预计这可能会因讽刺而被否决,但请注意我没有。我已经通读了几次提供的链接(由上面的 Raj More 提供),并认为它确实具有一些很好的内在价值(因为我是数据库开发的新手,所以有些概念在我脑海中浮现)。我添加了一个更新,您可以提供评论。 您(或者我自己也意识到了,哈哈)在考虑无用数据时实际上提出了一个很好的观点。我可以看到上面表 2 中的 ID 之类的唯一好处只是查看插入内容的时间和顺序(尽管日期也可以完成此操作)。 好吧,那么它不是ID(dentifier),而是一个排序。并且有很多情况下,自动生成的ID与插入的顺序不一样(UUID、并发线程、主从数据库等场景)。【参考方案2】:

我是代理键的忠实粉丝。我还没有看到我不想使用的场景。

我会说是的

阅读这个答案Surrogate vs. natural/business keys

编辑

我将更改我的答案以包括以下内容:

在某些情况下,我现在使用实际值作为代理键:

DimDate (20151031, 20151101, 20151102....) DimZipCode (10001, 10002, 10003...)

其他所有东西都有代理键。

【讨论】:

每张桌子?例如,带有Code, Name 字段的表Country 最好使用Code CHAR(2) Primary Key 定义。 如果我有一个国家代码的错误数据并且需要在维度中进行更改,那么我将不得不更新我的整个事实表,我的事实索引可能会不同步.另外我宁愿不级联更新 @Raj More - 添加了补充更新,我认为这最终突出了我的问题。在示例中,即使实际信息是相关的,每个表的“自动递增”ID 也会有所不同。随着越来越多的表被添加,“自动递增”的值似乎变得徒劳,只是一个行数。 如果您有不良数据,那么这是您能想到的最好的理由,就是不让他们进入您的数据库。如果有人告诉您他居住在 ISO 代码 XQ 的国家,那么您是认为您的 ISO 代码列表已过时,还是认为该人是骗子?【参考方案3】:

是的,有一个例外:

一个在其他两个表之间实现 n:m 关系的表,一个纯链接表,如果它只有两个字段,则不需要这样的字段,引用链接表的两个主键。链接表的主键则由这两个字段组成。

只要链接表有额外的信息,它就需要一个简单的单字段主键。

话虽如此,可能还有更多的例外;数据库设计是一个非常广泛的领域...

编辑:在上一句中添加了更多

【讨论】:

如果链接表将在下游的任何进一步关系中使用,现在您拥有更大的 FK(和更大的索引)。考虑减少此类链接表的 3 个关系 - 一组 8 列而不是 3 列的 FK。就个人而言,我宁愿从代理键开始。 @Raj,你是对的;如果链接表将在下游的任何进一步关系中使用,它不再是一个简单的链接表,它也有额外的信息。我同意在这种情况下添加代理键。 那么有一个异常(本身就有异常),可能还有其他异常?! @onedaywhen:是的,类似的。我试图贡献我们的经验法则,我将插入缺少的单词“更多”。顺便说一句,这个主题似乎释放了很多感情:) @onedaywhen - 您投票结束了一个问题,因为答案可能有例外?这很有意义....

以上是关于每个 MySQL 表都应该有一个自动递增的主键吗?的主要内容,如果未能解决你的问题,请参考以下文章

每个表都应该有一个主键吗?

SQL中的每一张表都必须设有主键吗

SQL中的每一张表都必须设有主键吗

SQL Server CE 中的每个表都必须有一个主键吗?

可以依赖数据库中的自动递增主键吗?

在单个 INSERT 查询中插入多行会保证顺序自动递增主键吗?