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

rta7y2nd  于 2021-08-09  发布在  Java
关注(0)|答案(3)|浏览(345)

我正在创建一个数据库,我不确定我的一个表。此表存储每个游戏中的用户,因此每个游戏中每个用户有一个条目。用户由其 user_id 这是一个36个字符的uuid4,游戏由 session_id 它是一个8个字符的字母数字字符串,如“abk2rxn4”。目前,我已经创建了一个名为 id 它是一个自动递增的整数,我把它设为主键。这是仅有的3个字段。
因为 session_id 以及 user_id 将始终产生唯一的结果,我是否应该使用这两个作为复合私钥并删除 id 场?
谢谢。
编辑:
如果我们有一个需要更多字段的更复杂的表,情况会改变吗?以这张table为例。

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

这与游戏中的投票有关。基本上在每一轮之后,游戏中的用户都会对游戏中其他用户的答案进行投票。所以每个条目都有 voter ,用户的用户名 voting_for ,当前 round ,的 category_id 不管他们是否同意答案, acceptable. 因此,您可以使用 voter , voting_for , round 以及 category_id . 仅仅因为有更多的字段,这会更糟吗?或者我应该仍然使用复合键而不是现有的自动递增键吗 id ?

ktecyv1j

ktecyv1j1#

那要看情况了。
如果桥牌表将包含任何其他列,这些列是用户和游戏之间关系的属性(例如, JoinedGameDate 或者你做了什么),那么行应该有自己的id,因为这听起来像是你的设计模式,表结构的一致性有一定的价值。虽然扔了一个 UNIQUE 索引这两个值不是个坏主意。
另一方面,如果它真的只是一个定义n:n关系的桥梁,那么您可以不必定义一个复合键,它将负责您的索引,并且到此为止。
另一方面,一个额外的自动增量的开销是非常小的,因此无论您选择哪种方式,决策对性能的影响可能都可以忽略不计。

dluptydi

dluptydi2#

“每个游戏每个用户一个条目”是这样说的 PRIMARY KEY(session_id, user_id) 这张table不错 entry . (将哪个id放在第一位取决于您最常运行的查询。)
不过,既然加起来是44个字节,让我们再想想。
中的每个二级索引 entry 表中有一个pk的副本,悄悄地钉在上面。如果您有多个二级索引,这可能会变得庞大。
另外,如果有其他表链接到 entry ,他们(通常)需要一份完整pk的副本,这可能会让他们更胖。
有人说,当我们审视所有这些事情的实际表现时,有几个因素 (id) 会更快,有人说会导致 (session_id, user_id) 更快。
因此,速度和空间将取决于许多细节,你还没有提出。
同时,您可以通过将uuid缩减为二进制(16)来提高速度和空间,二进制小20个字节(去掉破折号,用 UNHEX() ; 倒过来倒过来。如有需要,请提供更多详细信息。)
但是uuid还有一个速度问题。它们非常随机。因此,每个插入和请求的每一行都是随机查找。如果您有足够的ram让所有使用uuid的表都完全位于ram中,那么这不是什么大问题。否则,性能将很差,并且随着表的增大而变得更糟。
难道不应该有一个 session_id 在table上 voting_for ? 会有吗 JOINs 到其他table/从其他table?也许你只需要 PRIMARY KEY(session_id, voter, voting_for) . 至少能把游戏的信息聚集在一起。
提示和更多讨论:

  • UUID编号:http://mysql.rjweb.org/doc.php/uuid
  • 多对多Map:http://mysql.rjweb.org/doc.php/index_cookbook_mysql#many_to_many_mapping_table
vwhgwdsa

vwhgwdsa3#

您的桥接表基于两列。两者都不可为null,并且您希望对它们有唯一的约束,以便没有重复项。
这使得列已经成为表的键。”“主键”只是一个这样的键的名称。您可以保持原样(即声明列 NOT NULL 对他们有一个独特的约束)。您还可以将其声明为“主键”。这实际上不会改变什么。
您还可以决定添加一个技术性的单列键(建议使用整数id)。那么您的表将有两个唯一的键。后者可用于从另一个表(如果存在这样的表)更容易地引用行。一些使用基于技术id的数据库的人希望每个表都有这样的id,但只要不需要引用,就不必这样做。哪一个键(id或复合键)以及如果您再次调用“primary”则没有实际效果。通常您会将id称为主键。

相关问题