我应该创建代理键而不是复合键吗?

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

结构:

Actor <=== ActorMovie ===> Movie

ActorMovie: ActorID (fk), MovieId (fk)... ===> pk: (ActorID, MovieID)

我应该为这样的

ActorMovie
表创建一个代理键吗?

ActorMovie: ActorMovieID (pk), ActorID (fk), MovieId (fk)...
mysql database database-design surrogate-key
7个回答
8
投票

如果有帮助的话,约定就是好的

“SQL 反模式”,第 4 章,“需要 ID”

主键的含义

主键 - 您可以使用它在表中的唯一地址来识别您的行。这意味着,不仅某些代理列可以是主键。事实上,主键应该是:

  • 独特。每行的标识符。如果它是复合的,则意味着列值的每个组合都必须是唯一的
  • 最小。这意味着,它不能被减少(即,如果它是复合的,则不能在不失去唯一性的情况下省略任何列)
  • 单身。不能定义其他主键,每个表只能有一个主键

化合物与替代物

在某些情况下,代理键有好处。最常见的问题 - 如果您有包含人名的表。

first_name
+
last_name
+
taxpayer_id
的组合可以是唯一的吗?在大多数情况下 - 是的。但理论上,可能会出现重复的情况。因此,在这种情况下,代理键在任何情况下都将提供行的唯一标识。

但是,如果我们谈论表之间的多对多链接,很明显,链接表将始终包含每对一次。事实上,您甚至需要在操作该表之前检查是否不存在重复项(否则 - 它是冗余行,因为它不包含任何附加信息,除非您的设计有特殊意图来存储该信息)。因此,您的

ActorID
+
MovieID
组合满足主键的所有条件,并且 不需要 创建代理键。您可以这样做,但这没有什么意义(如果没有的话),因为它比对行进行编号没有任何意义。另一方面,使用复合键,您将拥有:

  • 独特的检查设计。您的行将是唯一的,链接表不允许有重复项。这有道理:因为如果链接已经存在,则无需创建链接
  • 设计中没有冗余(因此不太全面)的列。这使您的设计更容易、更具可读性。

作为结论 - 是的,在某些情况下,应该(甚至必须)应用代理键,但在您的特定情况下,它肯定会是反模式 - 使用复合键。

参考资料:


4
投票

我总是使用复合键。我的推理:

  • 您可能永远不会在任何地方使用代理键。
  • 您将减少表上索引/约束的数量,因为您肯定仍然需要演员和电影的索引。
  • 无论如何,你总是会搜索电影或演员。

除非您实际在自己的表之外使用代理键,否则我会使用复合键。


4
投票

让我提一下其他发帖者似乎忽略的一个细节:InnoDB 表是集群的

如果你只有一个主键,你的整个表将由一个单独的 B 树表示,这是非常高效的。添加代理只会创建另一个 B 树(并且由于集群的工作原理,比预期启动时“更胖”),而没有任何好处来抵消增加的开销。

代理有其位置,但联结表通常不是。


1
投票

如果您想将其他数据元素与连接表关联起来,例如所扮演的角色的名称(可能是子表),那么我当然会这样做。如果你确定你从来不想那么我会认为它是可选的。


1
投票

考虑数据库设计规范化的第一范式(1NF)。

我会将 ActorID 和 MovieID 作为唯一的键组合,然后创建主键 ActorMovieID。

在这里看到同样的问题:两个外键而不是主键


0
投票

在这个主题上,我的观点非常简单:代理主键始终有效,而复合键可能并不总是有效这些天,这有多种原因。

所以当你开始问自己“复合是否比代孕更好”时,你就已经进入了浪费时间的过程。去找代孕妈妈吧它总是有效的。并切换到下一步。


0
投票

如果您有 n 个中间表,没有任何其他附加字段,请使用复合键。

如果“中间”表有附加字段,则不是一个简单的中间表。然后,拥有代理键会更好,因为对其他字段进行索引和查询会更加高效。

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