Sql server SQL Server中的多对多关系结构是否有额外的主键列?

Sql server SQL Server中的多对多关系结构是否有额外的主键列?,sql-server,performance,structure,Sql Server,Performance,Structure,假设我们有两个表:角色和报告。存在着 他们之间的多对多关系。当然,唯一的解决办法 我想到的是创建一个交叉表,让我们把它命名为RoleReport。 我可以看到该表结构的两种方法: 1. Columns: RoleReportId, RoleId, ReportId PK: RoleReportId 2. Columns: RoleId, ReportId PK: RoleId, ReportId 它们(性能或其他方面)之间有什么区别吗?您实际上不需要角色报告。这对关系没有任何影响

假设我们有两个表:角色报告。存在着 他们之间的多对多关系。当然,唯一的解决办法 我想到的是创建一个交叉表,让我们把它命名为RoleReport。 我可以看到该表结构的两种方法:

1. Columns: RoleReportId, RoleId, ReportId
   PK: RoleReportId
2. Columns: RoleId, ReportId
   PK: RoleId, ReportId
它们(性能或其他方面)之间有什么区别吗?

您实际上不需要角色报告。这对关系没有任何影响

许多人试图避免在实际表中使用自然唯一的键,而是选择人工唯一的键,但我并不总是同意这一点。例如,如果您可以确保您的SSN永远不会更改,则可以将其用作密钥。如果将来它确实发生了变化,那么你就可以修复它


但我不想争论这一点,双方都有很好的论据。但是,在这种情况下,您当然不需要人为的唯一键,因为您的其他两个字段都是唯一的,并且将保持唯一。

除非您确实需要
角色报告
作为其他表中的外键(通常不会是这种情况),请使用选项2。它将需要更少的存储空间,而这本身可能会带来性能优势——加上为什么有一个永远不会使用的列?

从语义上讲,区别在于您使用的主键是什么

通常,我会让模式的其余部分决定我在这种情况下的操作。如果交叉表是多对多关系的专用实现,我倾向于使用连接主键。如果我在交叉表上挂起更多的信息,使之成为一个独立的实体,我更倾向于给它自己的id,而不依赖于它所连接的两个表


当然,这是主观的。我不认为这是唯一正确的方法(tm)。

我建议你选择第二种方法时不要使用PK。您可以在两列的组合上使用索引或唯一约束。

无论如何(
RoleId,ReportId
)上都需要一个复合的
unique
索引

如果不使用
主键
,就没有意义了

如果使用
集群主键执行此操作(这是默认设置),则性能会更好,因为它的大小会更小

聚集主键在每个记录中只包含两列:
RoleID
ReportID
,而次索引将包含三列:
RoleID
ReportID
RoleReportID
(作为行指针)

您可能需要在
ReportID
上创建一个附加索引,该索引可用于搜索给定
报告的所有
角色

如果满足以下两个条件,则为该关系创建代理键是有意义的:

  • 您的关系中有其他属性(即此表包含其他列,如
    Date
    或其他任何内容)
    • 您拥有大量表,这些表使用
      外键引用此关系
  • 在这种情况下,最好在
    外键
    关系中使用一列
    主键


    由于您似乎不需要这样做,如果您有许多行,只需创建一个复合的
    主键

    ,那么在RoleId和/或ReportId列上具有适当排序的索引可能会有所帮助,因为这将加快查找操作,但反过来会减慢插入/删除操作。这是一个典型的使用配置文件问题

    如果没有其他要求,请省略
    rolerereportid
    PK。它不向关系中添加任何内容,强制服务器在每次插入时生成一个无用的数字,并使其他两列无序,这会降低查找速度


    但总而言之,我们这里讲的是毫秒。只有当存在大量数据(比如超过10000行)时,这才有意义。

    当您(或其他人,取决于您公司的结构)需要编写一个前端来处理各个角色报告关系(例如,删除一个)时,使用角色报告ID作为单列主键的好处就出现了. 在这一点上,您可能更喜欢只需要寻址一列而不是两列来标识链接记录


    除此之外,您不需要RoleReportID列。

    为什么不创建用于数据关系的人工数据?这样你就不必想:RoleReportId永远不会改变,但是性能呢?使用第一个选项是因为我在一个字段上有一个PK,第二个选项是在两个字段上。它有意义吗?@rafek:re perf:试试看。数据库优化器可能非常聪明,也可能不聪明,这取决于不在本文讨论范围内的所有内容。@rafek,不应该如此。索引只是基础数据的有序列表。数据是来自一个字段还是两个(连续)字段并不重要,特别是因为在普通数据库中,读远远大于写。@Rubens,我假设roleid和reportid都已经是人工唯一键,因为作者似乎喜欢它们:-)在这种情况下,你只是在浪费空间,因为如果这两个都不改变,你就不需要另一个人工唯一的密钥。你的答案超出了我的预期。非常感谢!:)