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

时间:2013-11-25 10:11:10

标签: mysql database database-design

结构:

Actor <=== ActorMovie ===> Movie

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

我应该像这样为ActorMovie表创建一个代理键吗?

ActorMovie: ActorMovieID (pk), ActorID (fk), MovieId (fk)...

6 个答案:

答案 0 :(得分:8)

如果有用,则约定很好

“SQL Antipatterns”,第4章,“需要ID”

主键的意图

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

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

复合与代理

有些情况下代理密钥有好处。最常见的问题 - 如果你有人名的表。 first_name + last_name + taxpayer_id的组合可以是唯一的吗?在大多数情况下 - 是的。但从理论上讲,可能会出现重复发生的情况。因此,当代理键在任何情况下都会提供行的唯一标识时就是这种情况。

但是,如果我们谈论表之间的多对多链接,很明显,链接表将始终包含每对一次。实际上,在使用该表之前,您甚至需要检查是否存在重复项(否则 - 它是冗余行,因为除非您的设计有特殊意图存储,否则它不会包含其他信息)。因此,ActorID + MovieID的组合满足主键的所有条件,并且无需来创建代理键。你可以这样做,但这没有任何意义(如果不是),因为它没有意义而不是编号行。另一方面,使用复合键,您将拥有:

  • 独特的设计检查。您的行将是唯一的,不允许链接表重复。并且有意义:因为如果链接已经存在则无需创建链接
  • 设计中没有冗余(因此,不太全面)的专栏。这使您的设计更容易,更易读。

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

参考文献:

答案 1 :(得分:3)

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

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

除非您有实际使用代理键的方案,否则我会使用复合键。

答案 2 :(得分:2)

我只想提一下其他海报似乎遗漏的细节:InnoDB tables are clustered

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

Surrogates have their place,但结点表通常不是它。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

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

在此处查看相同的问题:Two foreign keys instead of primary

答案 5 :(得分:1)

关于这个问题,我的观点很简单:代理主键总是可以工作,而复合键可能不会总是工作这些天中的一天,这有多种原因

因此,当你开始问自己'复合优于代理'时,你已经进入了浪费时间的过程。去代理。它总是有效。然后切换到下一步。