由许多键组成的复合键是否会影响性能?

时间:2016-07-14 09:33:37

标签: sql sql-server tsql

我的情况是复合键由5个或更多个键组成,如下所示。

选项1:

Test table:
schoolid
testid  --composite Primary key on both the columns

TestStudent table:
schoolId
testId
studentId  -- composite primary key of all columns

TestStudentMCQ table:
schoolid
testid
studentid
choiceid  --composite Primary key of all columns

我可以将Test表的PK设为TestId,以便MCQAnswer表格具有TestId, StudentId, QuestionId and ChoiceId

如果性能影响不显着,我更愿意选择第一个选项。

此外,我将RLS与SchoolId一起使用。

我还想在这里提一下:

我还有另一个表TestStudent,它具有如上所示的复合主键。同样的事情可以设计如下。

选项2:

Test table:
schoolid
testid  --composite Primary key on both the columns

TestStudent table:
id
schoolId
testId
studentId  -- id is the identity primary key here

TestStudentMCQ table:
testStudentId
choiceid  --composite Primary key of both columns

哪种方法更好?

4 个答案:

答案 0 :(得分:3)

名称主键源自ISAM和其他数据库类型的关系前日期,不幸的是,Codd,Date等人将其加入 relational 术语作为逻辑设计的一部分。我不幸地说,因为大型关系供应商随后将其作为性能最佳外键查找机制的规范 - 物理设计属性重新选择回物理设计。 / p>

由于这种混淆,我尽可能避免使用术语主键。逻辑设计中有自然(或业务)键,物理设计中有代理键。是否在特定表上使用代理键的决定是一个棘手的问题,但可以说一件事:如果已知表从不超过大约50到200行,则引擎可能永远不会使用索引查找,因此不需要代理密钥。毋庸置疑,出于逻辑和物理设计的原因,所有自然或代理的密钥都应由Unique Indices强制执行。

然而,这是一个关系表的原则,也就是说,在第一范式中,每个表都有一个自然(或商业)密钥。由于代理密钥永远不会向用户公开,因此这种自然业务密钥成为用户指定单个行的唯一方法。

当选择实施代理密钥时,用于强制执行该密钥的索引几乎总是最佳地成为聚集索引。

解决您的特定问题:是的,大型复合键上的 聚集索引 肯定会影响包含超过100或200行的表的性能 。使用非聚集索引强制执行(复合)自然键,并可能向该索引添加一些精心选择的其他 coverage字段。使索引强制您的代理键成为聚簇索引,除非您有非常好的和有充分记录的理由否则。

原因是:

  • 索引高度与键宽度成反比。宽复合索引可以有一个或两个(或更多!)级别小于较窄的索引,需要更多的软页面和硬页面错误以及更多的缓存使用,这不仅会影响表本身的查找性能,还会影响表格所服务的所有内容。发动机。

  • 除非由该索引覆盖,否则每次通过非聚集索引进行查找都需要通过聚簇索引键进一步查找聚簇索引。使聚簇索引查找有效是非常重要的,因为它们控制 所有 查找的效率。

最后,请记住记录所有聚类和索引决策及其在逻辑和物理设计中的影响和基本原理。 DBA会定期审查物理设计决策,以确定调整性能的方式和方法 - 但严格按照逻辑设计 做出的决策绝不能因性能原因而改变 。帮助你的DBA,并清楚地标记哪些是。

答案 1 :(得分:0)

由多个键组成的复合键是否会影响性能?

是的,如果您指的是如何在这些主键上创建聚簇索引,它会影响性能,因为您在聚簇索引中使用的键将是它将遵循的排序模式,如果您创建Non-聚簇索引,它将使用您在聚簇索引中使用的键作为书签来引用数据行,这就是它应该唯一,简短和静态的原因。防止性能问题,

但是如果你只讨论主键,那么不,它只会根据你使用的复合主键来决定行的唯一性。

答案 2 :(得分:-1)

我们应该区分主键约束和聚簇索引。默认情况下,SQL Server会创建一个CI以支持PK约束,但可以覆盖它。

主键是唯一的并且标识一行(在您的情况下,如果testid本身是唯一的,则向其添加任何其他列将是错误的)。聚簇索引不需要是唯一的,并且会影响表中数据行的物理布局。

如果其他表引用了表,则主键也用于FK。如果是这种情况,如果它是单列,则更方便。

出于性能原因,聚簇索引应该是窄的,不断增加的和不可变的。缩小,因为每个NCI都将包含整个CI作为指向行数据的指针。增加以防止页面拆分和碎片。不可变,因为对它的任何改变都会导致所有NCI被更新。

Tl; dr,对于主键,如果没有理由反对,我会使用商业密钥。对于CI,我会考虑先使用序列。

答案 3 :(得分:-2)

主键的聚簇索引将复制到所有非聚簇索引,从而增加其大小。对于中小型表而言,这可能并不明显,但在大型表上,您希望争取单个字节以尽可能减少表大小(特别是对于数据仓库的事实表)。

因此,对于中小型表,您可能希望将业务键作为主键 - 在这种情况下,所有列的组合 - 使用此方法,连接表和关系列变得更具可读性。对于大型表,您可能希望将代理自动增量整数作为主键,并在业务键上创建UNIQUE约束(在您的情况下为复合)。