15

很明显,我们已经有了每个用户的另一个唯一信息,那就是用户名。那么,为什么我们需要为每个用户提供另一个独特的东西呢?为什么我们还应该为每个用户创建一个 id?如果我们省略 id 列会发生什么?

4

5 回答 5

17

即使您的用户名是唯一的,使用额外的 id 列而不是使用 varchar 作为主键也没有什么好处。

  • 有些人更喜欢使用整数列作为主键,作为永远不需要更改的代理键,即使其他列可能会发生变化。尽管自然主键也无法更改,但您必须使用级联外键约束来确保相关表中的外键与任何此类更改同步更新。

  • 主键是 32 位整数而不是 varchar 可以节省空间。在引用您的用户表的所有其他表中选择 int 或 varchar 外键列可能是一个很好的理由。

  • 如果将新行添加到索引的末尾,与将它们楔入索引中间相比,插入到主键索引的效率会更高一些。MySQL 表中的索引通常是 B+Tree 数据结构,您可以研究这些以了解它们的性能。

  • 一些应用程序框架更喜欢这样的约定,即数据库中的每个表都有一个名为 的主键列id,而不是使用自然键或复合键。遵循这样的约定可以使某些编程任务更简单。

这些问题都不是交易破坏者。使用自然键也有好处:

  • 如果按用户名查找行比按 id 搜索更多,最好选择用户名作为主键,并利用 InnoDB 的索引组织存储。如果可能的话,让你的主查找列成为主键,因为主键查找在 InnoDB 中更有效(你应该在 MySQL 中使用 InnoDB)。

  • 正如您所注意到的,如果您已经对用户名有一个唯一约束,那么保留一个您不需要的额外 id 列似乎是一种存储浪费。

  • 使用自然键意味着外键包含人类可读的值,而不是任意整数 id。这允许查询使用外键值,而不必连接回父表以获得“真实”值。

关键是没有涵盖 100% 案例的规则。我经常建议你应该保持你的选择开放,即使在单个数据库中也可以使用自然键、复合键和代理键。

我在我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming 的“需要 ID”一章中介绍了代理键的一些问题。

于 2013-04-03T01:24:23.673 回答
8

此标识符称为代理键。我链接的页面列出了优点和缺点。

在实践中,我发现它们是有利的,因为即使是超级键数据也会随着时间而改变(即用户的电子邮件地址可能会改变,因此任何对应关系都必须改变),但是代理键永远不需要改变它所识别的数据,因为它的value 对关系没有意义。

从一个JOIN角度来看,它也很好,因为它可以是一个具有比 varchar 更小的密钥长度的整数。

我可以说在实践中我更喜欢使用它们。由于开发过程中需求的变化,我被多次使用跨表使用的多列主键或数据表示超键不得不变得非唯一,这不是你想要处理的情况。

于 2013-04-03T01:13:41.213 回答
3

在我看来,每个表都应该有一个唯一的、自动递增的 id。

以下是一些实际原因。如果您有重复的行,您可以轻松确定要删除的行。如果您想知道插入行的顺序,您可以在 id 中找到该信息。至于用户,世界上不止《约翰·史密斯》。id 为外部引用提供了一个键。

最后,几乎任何可以描述用户的东西——姓名、地址、电话号码、电子邮件地址——都可能随着时间而改变。

于 2013-04-03T01:06:50.977 回答
3

我有 mysql。

 1:Index fields 2:Unique fields and 3:PK fields.
index means pointable
unique means in a table must be one in all rows.
PK = index + unique

在一个表中,您可能有许多独特的字段,例如
用户名或护照代码或电子邮件。
但你需要一个像 ID 这样的字段。这既是唯一的又是索引(=PK)。第一个总是一回事,永远不会改变,第二个是唯一的,第三个很简单(因为通常是数字)。

于 2013-04-03T01:08:01.890 回答
2

使用数字 id 的一个原因是在其上创建索引比在文本字段上更精简,从而减少了查找特定用户所需的索引大小和处理时间。此外,当交叉引用不同表中的用户(关系数据库)时,节省的字节数也更少。

于 2013-04-03T01:06:41.270 回答