Sql server 在连接表中,我应该使用主键和唯一约束,还是使用复合/复合键?

Sql server 在连接表中,我应该使用主键和唯一约束,还是使用复合/复合键?,sql-server,tsql,compound-key,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

我已经读了一大堆似乎会使这成为一个重复问题的东西。但通读所有这些让我感到不确定。我希望根据下面的绝对示例得到答案,因为许多问题/答案都会在辩论中反复出现

如果我有:

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关系-也使用“删除时级联”

BookID和AuthorID上的外键关系,以及删除时的级联。还可以在BookID和AuthorID上设置唯一约束

我正在寻找一个简单的答案,来解释为什么在上面的例子中,一种方法比另一种更好。我正在阅读的答案非常详细,我正要确定一个复合键,但随后观看了一个视频,其中示例使用了一个标识栏,就像我的第一个示例一样

这个话题似乎有点一分为二,但我的直觉告诉我,我应该使用复合键


什么查询更有效?它似乎有一个PK identity列,同时在这两个列上设置了一个唯一的约束,而FK关系的成本会更高,即使有一点。

我更喜欢第一个设计,使用复合键。即使父表中有标识列,但在连接表中有标识列也不会给您带来好处。您不会使用标识列查询
BookAuthor
,而是使用
BookID
AuthorID
查询它

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


此外,如果主键是
(BookID,AuthorID)
,则需要在
AuthorID,BookID)
上建立索引。如果你想查询作者写的书,这将很有帮助

作为代理键好处的坚定支持者和改革者,我仍然对所有键联接表(如您的第一个示例)例外。代理键的一个好处是,作为默认和最常见的情况,引擎通常针对单个整数字段的连接进行了优化

您的第一个建议仍然可以获得这一好处,但每个索引级别上的风扇数量也增加了50%,从而减少了联接表上索引的总体大小和高度。尽管对于比大型表小的任何东西来说,这种方法的性能优势都可以忽略不计,但它是最佳实践,而且是免费的


我可能选择另一种设计的时候是关系是否会累积额外的列。此时,它不再是严格意义上的联接表。

您可能应该使用复合/复合键。通过这种方式,你完全是关系型的——一个作者可以写很多书,一本书可以有多个作者。

这是我在大学数据库课程中一直记得的。我们讨论了教科书中关于“实体设计”的部分,它讨论的是连接表。。。我们称之为相交表或相交关系。那天我在课堂上真的很专心。这位教授说,根据他的经验,多对多连接表几乎总是表示一个未识别的缺失实体。这些实体几乎总是以自己的数据结束

我们得到了一个
学生
课程
实体的例子。对于一个学生来说,你需要把这两门课结合起来。结果,您实际拥有的是一个新实体:
注册
。在这种情况下,额外的数据可能是信用类型(审计与常规)或最终等级

我至今还记得那个建议。。。但我并不总是遵循它。在这种情况下,我要做的是停止,并确保在这个问题上回到利益相关者那里,与他们一起研究我们在这个连接点上可能仍然缺少的数据点。如果我们真的找不到任何东西,我就用复合键。当我们找到数据时,我们会想到一个更好的名称,它会得到一个代理密钥

2020年更新
我仍然有这本教科书,令人惊讶的巧合是,它和这个问题在几个小时内就引起了我的注意。对于好奇的人来说,这是本书第七版的第五章第六节:


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

减少存储开销 假设您将使用代理密钥。由于您可能需要查询特定书籍的所有作者,而vica也需要查询特定书籍的所有作者,因此您需要以BookId和AuthorId开头的索引。出于性能原因,应该在两个索引中都包含另一列,以防止聚集键查找。您可能希望将其中一个设置为唯一,以确保表中没有添加重复的BookId/AuthorId组合

因此,最终结果是:

  • 数据存储3次,而不是2次
  • 将验证2个唯一约束,而不是1个
查询连接表引用表
即使您要添加一个类似于
Contributions(AuthorId,BookId,…)
的表来引用连接表。大多数查询根本不需要触及连接表。例如:要查找特定作者的所有贡献,将只涉及作者和贡献表。

根据连接表中的数据量,复合键最终可能会导致自动生成的顺序主键性能不佳

主键是表的聚集索引,这意味着它决定了行在磁盘上的存储顺序。如果主键的值不是按顺序生成的(例如,它是
dbo.BookAuthor
--------------
RecordID PK int identity(1,1)
BookID FK
AuthorID FK