在联结表中,我应该使用主键和唯一约束,还是复合/复合键?

时间:2015-03-03 23:22:28

标签: sql-server tsql compound-key

我已经阅读了一些似乎使这个问题成为重复的问题。但阅读所有这些让我不确定。我希望能够根据下面的绝对示例得到答案,因为很多问题/答案会来回讨论。

如果我有:

dbo.Book
--------
BookID PK int identity(1,1)

dbo.Author
----------
AuthorID PK int identity(1,1)

现在我有一个简单的联结表的两个选择:

dbo.BookAuthor
--------------
BookID CPK and FK
AuthorID CPK and FK

以上将是两个FK上的复合/复合键,以及为两列设置FK关系 - 在删除时也使用Cascade。

OR

dbo.BookAuthor
--------------
RecordID PK int identity(1,1)
BookID FK
AuthorID FK

BookID和AuthorID上的外键关系,以及删除时的Cascade。同时在BookID和AuthorID上设置唯一约束。

我正在寻找一个简单的答案,为什么一个方法比ABOVE特定例子中的另一个更好。我正在阅读的答案非常详细,而我正准备解决一个复合键,但后来观看了一个视频,其中示例使用了像我的第一个示例中的Identity列。

似乎这个主题略微被撕成两半,但我的直觉告诉我,我应该只使用复合键。

查询效率更高?它似乎有一个PK标识列,同时在两列上设置了一个唯一约束,即使有一点点,FK关系也会更加昂贵。

6 个答案:

答案 0 :(得分:10)

这是我在大学期间从数据库课程中一直记得的东西。我们正在讨论关于“实体设计”的教科书中的部分,它正在谈论连接表......我们将它们称为交叉表或交叉关系。这位教授说,根据他的经验,多对多联合表几乎总是表明一个未被识别的缺失实体。这些实体几乎总是以自己的数据结束。

我们获得了学生和课程实体的示例。对于学生参加课程,您需要在这两者之间建立联系。你实际拥有的是一个新实体:一个注册。在这种情况下,其他数据可能是信用类型(审计与常规)或最终等级。

我记得今天的建议......但我并不总是遵循它。在这种情况下我要做的是停止,并确保回到问题的利益相关者,并与他们一起处理我们在这个联结中可能仍然缺少的数据点。如果我们真的找不到任何东西,那么我将使用复合键。当我们找到数据时,我们会想到一个更好的名称,它会得到一个代理键。

答案 1 :(得分:4)

作为代理键的好处的坚定支持者和传播者,我不例外地为所有关键连接表例如你的第一个例子做了例外。代理键的一个好处是引擎通常针对连接单个整数字段进行了优化,作为默认和最常见的情况。

您的第一个提案仍然可以获得此优势,但每个索引级别的粉丝投放量也增加了50%,从而减少了联接表上索引的总体大小和高度。虽然对于任何小于大型桌子的东西来说,这种性能优势可以忽略不计,但这是最好的做法,而且是免费的。

当我选择其他设计时,如果关系是累积其他列。此时它不再是严格的连接表。

答案 2 :(得分:3)

使用复合键也是我的选择。原因如下:

减少存储开销

假设你要使用代理键。既然你可能想要查询所有作者的特定书籍,反之亦然,你需要从BookId和AuthorId开始的索引。出于性能原因,您应该在两个索引中包含另一列以防止群集密钥查找。您可能希望使其中一个是唯一的,以确保没有重复的BookId / AuthorId组合添加到表中。

所以作为最终结果:

  • 数据存储3次而不是2次
  • 要验证2个唯一约束,而不是1

查询引用表

的联结表

即使您添加了一个引用联结表的Contributions (AuthorId, BookId, ...)表。大多数查询都不需要触摸联结表。例如:找到特定作者的所有贡献只涉及作者和贡献表。

答案 3 :(得分:3)

根据联结表中的数据量,复合键可能最终会导致自动生成的顺序主键的性能下降。

主键是表的聚集索引,这意味着它确定行在磁盘上的存储顺序。如果主键的值没有按顺序生成(例如,它是由表中的外键组成的复合键,其中行与联结表的行的顺序不同,或者它是GUID或其他随机键),则每次将一行添加到联结表中,将需要重新组合表的行。

答案 4 :(得分:2)

我更喜欢第一种设计,使用复合键。即使父表具有它们,在联结表上具有标识列也不会给您带来好处。您不会使用标识列查询BookAuthor,而是使用BookIDAuthorID进行查询。

此外,添加标识将允许重复的BookID - AuthorID组合,除非您设置了约束。

此外,如果您的主键为(BookID, AuthorID),则需要AuthorID, BookID)上的索引。如果您想查询作者撰写的书籍,这将有所帮助。

答案 5 :(得分:1)

您可能应该使用复合/复合键。这样你就完全是关系型的 - 一个作者可以写很多书,一本书可以有多个作者。