我已经阅读了一些似乎使这个问题成为重复的问题。但阅读所有这些让我不确定。我希望能够根据下面的绝对示例得到答案,因为很多问题/答案会来回讨论。
如果我有:
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关系也会更加昂贵。
答案 0 :(得分:10)
这是我在大学期间从数据库课程中一直记得的东西。我们正在讨论关于“实体设计”的教科书中的部分,它正在谈论连接表......我们将它们称为交叉表或交叉关系。这位教授说,根据他的经验,多对多联合表几乎总是表明一个未被识别的缺失实体。这些实体几乎总是以自己的数据结束。
我们获得了学生和课程实体的示例。对于学生参加课程,您需要在这两者之间建立联系。你实际拥有的是一个新实体:一个注册。在这种情况下,其他数据可能是信用类型(审计与常规)或最终等级。
我记得今天的建议......但我并不总是遵循它。在这种情况下我要做的是停止,并确保回到问题的利益相关者,并与他们一起处理我们在这个联结中可能仍然缺少的数据点。如果我们真的找不到任何东西,那么我将使用复合键。当我们找到数据时,我们会想到一个更好的名称,它会得到一个代理键。
答案 1 :(得分:4)
作为代理键的好处的坚定支持者和传播者,我不例外地为所有关键连接表例如你的第一个例子做了例外。代理键的一个好处是引擎通常针对连接单个整数字段进行了优化,作为默认和最常见的情况。
您的第一个提案仍然可以获得此优势,但每个索引级别的粉丝投放量也增加了50%,从而减少了联接表上索引的总体大小和高度。虽然对于任何小于大型桌子的东西来说,这种性能优势可以忽略不计,但这是最好的做法,而且是免费的。
当我选择其他设计时,如果关系是累积其他列。此时它不再是严格的连接表。
答案 2 :(得分:3)
使用复合键也是我的选择。原因如下:
假设你要使用代理键。既然你可能想要查询所有作者的特定书籍,反之亦然,你需要从BookId和AuthorId开始的索引。出于性能原因,您应该在两个索引中包含另一列以防止群集密钥查找。您可能希望使其中一个是唯一的,以确保没有重复的BookId / AuthorId组合添加到表中。
所以作为最终结果:
即使您添加了一个引用联结表的Contributions (AuthorId, BookId, ...)
表。大多数查询都不需要触摸联结表。例如:找到特定作者的所有贡献只涉及作者和贡献表。
答案 3 :(得分:3)
根据联结表中的数据量,复合键可能最终会导致自动生成的顺序主键的性能下降。
主键是表的聚集索引,这意味着它确定行在磁盘上的存储顺序。如果主键的值没有按顺序生成(例如,它是由表中的外键组成的复合键,其中行与联结表的行的顺序不同,或者它是GUID或其他随机键),则每次将一行添加到联结表中,将需要重新组合表的行。
答案 4 :(得分:2)
我更喜欢第一种设计,使用复合键。即使父表具有它们,在联结表上具有标识列也不会给您带来好处。您不会使用标识列查询BookAuthor
,而是使用BookID
和AuthorID
进行查询。
此外,添加标识将允许重复的BookID
- AuthorID
组合,除非您设置了约束。
此外,如果您的主键为(BookID, AuthorID)
,则需要AuthorID, BookID)
上的索引。如果您想查询作者撰写的书籍,这将有所帮助。
答案 5 :(得分:1)
您可能应该使用复合/复合键。这样你就完全是关系型的 - 一个作者可以写很多书,一本书可以有多个作者。