何时使用复合键而不是自动递增键?

问题描述 投票:0回答:1

我正在创建一个数据库,但我对其中的一个表不确定。这个表存储的是每个游戏中的用户,所以每个用户在每个游戏中都有一个条目。用户是通过他们的 user_id 是一个36个字符的UUID4,而游戏的标识是由一个 session_id 是一个8个字符的字母数字字符串,如 "ABK2RXN4"。目前,我已经创建了一个额外的字段,叫做 id 这是一个自动递增的整数,我已经将其设置为主键。只有这3个字段。

由于这些字段的组合是 session_iduser_id 的结果总是唯一的,我是否应该把这两个作为复合私钥,并去除了 id 领域?

谢谢。

EDIT.请问,如果我们有一个更复杂的表,需要更多的字段,情况会改变吗?

如果我们有一个更复杂的表,需要更多的字段,事情会发生变化吗?以这个表为例。

| id  | voter    | voting_for | round    | category_id | acceptable |
|-----|----------|------------|----------|-------------|------------|
| int | char(36) | char(36)   | smallint | int         | boolean    |

这是关于游戏中的投票。本质上,每一轮游戏结束后,游戏中的用户会对游戏中其他用户的答案进行投票。所以每一个条目都有用户的用户ID。voter的用户ID,他们是谁?voting_for,当前 roundజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజజ category_id 的类别,以及他们是否同意这个答案。acceptable. 所以,你可以用以下方法制作一个复合主键 voter, voting_for, roundcategory_id. 这是否会因为字段较多而变得更糟,或者我仍然应该使用复合键,而不是现有的自动递增。id?

mysql sql composite-primary-key
1个回答
0
投票

这要看情况。

如果桥表要包含任何其他列,这些列是用户和游戏之间的关系的属性(比如说。JoinedGameDate 或什么的),那么行可能应该有自己的ID,因为听起来这就是你的设计模式,表结构的一致性有一定的价值。虽然抛出一个 UNIQUE 索引在这两个值上并不是一个坏主意。

另一方面,如果它真的只是一个定义N:N关系的桥,你可以定义一个复合键,这将照顾到你的索引,然后收工。

另一方面,多出的那一个自动增量的开销是非常小的,所以无论你采用哪种方式,这个决定对性能的影响可能都会忽略不计。


0
投票

"每个用户每场比赛一个条目 "说的是 PRIMARY KEY(session_id, user_id) 对得起桌子 entry. (选择把哪个id放在第一位,取决于你运行最多的是什么查询)。

然而,由于这加起来有44个字节,我们再想想。

中的每个二级索引 entry 表有一个PK的副本,静静地粘在上面。 如果你有一个以上的二级索引,这可能会变得很笨重。

此外,如果你有其他表链接到了 entry,他们(通常)需要整个PK的副本,使他们潜在的更胖。

当我们看到所有这些东西的实际表现时,有 若干 因素,有人说 (id) 会更快,有人说会导致 (session_id, user_id) 是更快。

所以,速度和空间将取决于很多细节,你还没有介绍。

同时,你可以通过将UUID缩小到BINARY(16),也就是小20个字节的方式来帮助速度和空间。 (去掉破折号,然后用 UNHEX();反之则做反方向。 更多详情请咨询)。)

但是UUID还有一个速度问题。 它们是非常随机的。 所以,每次插入和请求的每一行都是随机查找。 如果你有足够的RAM,让所有使用UUIDs的表完全在ram中,那么这不是什么大问题。 否则,性能会很差,而且随着表的变大,性能会越来越差。

是不是应该有一个 session_id 表中 voting_for? 会不会有 JOINs 到其他表格? 也许你需要的只是 PRIMARY KEY(session_id, voter, voting_for). 这样至少可以把游戏的信息集中在一起。

技巧和更多的讨论。* UUIDs: http:/mysql.rjweb.orgdoc.phpuuid * 多对多映射。 http:/mysql.rjweb.orgdoc.phpindex_cookbook_mysql#many_to_many_mapping_table。


0
投票

您的桥表是基于两列的。这两列都是不可空的,你希望对它们有一个唯一的约束,这样就不会有重复。

这使得这两列已经是表的一个键。"主键 "只是这样一个键的名称。你可以不这样做(即把列声明为 NOT NULL 并对它们有一个唯一的约束)。) 你也可以将其声明为 "主键"。这实际上不会改变任何东西。

你也可以决定添加一个技术性的单列键(如你所建议的一个整数ID)。那么你的表将有两个唯一的键。后者可以用来从另一个表中更容易地引用一行,如果有这样的表的话。有些人在使用基于技术ID的数据库时,更喜欢每个表都有这样的ID,但只要你不需要引用,就没有必要。你又把哪个键(ID或复合键)以及是否有任何键称为 "主键 "没有实际影响。通常情况下,你会把ID称为主键。

© www.soinside.com 2019 - 2024. All rights reserved.