0

我有一系列有关SQL,SQL 2005中的键,索引和约束的问题。我一直在使用SQL大约4年,但我从来没有能够获得有关此主题的明确答案,并且博客文章中总是存在矛盾的信息等。我创建和使用的大多数时间表都只有一个Identity列是主键,其他表通过外键指向它。SQL 2005:键,索引和约束问题

在连接表中,我没有标识并在外键列上创建复合主键。以下是我对当前信仰的一系列陈述,这可能是错误的,如果是这样,请纠正我,以及其他问题。

所以这里有云:

据我了解一个聚集和非聚集索引的区别(不管它是唯一与否)是聚集索引会影响表中的数据的物理顺序(因此在表中只能有一个),而非聚集索引构建树数据结构。在创建索引时,为什么我应该关心“群集”与“非群集”?我应该什么时候使用其中一种?我被告知插入和删除非聚集索引很慢,因为树需要“重建”。我认为聚集索引不会以这种方式影响性能?

我看到主键实际上只是聚集索引是唯一的(他们必须被聚集?)。主键与集群唯一索引有什么特别之处?

我也见过约束,但我从来没有用过它们或真的看过它们。有人告诉我,约束的目的是为了强制数据完整性,而索引是针对性能的。我也读过约束作为索引来实现,因此它们是“相同的”。这听起来不错,对我来说。约束如何与索引不同?

回答

2

正如你所说的那样,Clustered indexes是关于如何在物理上存储表中的数据的定义,即,你有一个使用集群密钥排序的B树,并且在叶级别有数据。

Non-clustered indexes另一方面是分离的树结构,它们在叶级别只有聚簇键(或者如果表是堆的话就是RID),这意味着当你使用非聚簇索引时,使用聚集索引来获取其他列(除非您的请求已完全由非聚集索引覆盖,如果您仅请求构成非聚集索引键列的列,则会发生这种情况)。

什么时候应该使用其中一种?那么,因为你只能有一个聚集索引,所以在最有意义的列上定义它,即当你大多数时候通过ID查找客户端时,在ID上定义一个聚集索引。非聚簇索引应该在较少使用的列上定义。

关于性能,更改索引键的插入或更新通常是痛苦的,无论它是否在非聚簇索引上被冻结,因为页面拆分可能发生,这会迫使数据在页面之间移动(移动页面聚集索引的伤害更大,因为叶级中有更多数据)。因此,一般规则是避免改变索引键并插入新值,以便它们是顺序的。否则,你会遇到碎片,并将不得不定期重建你的索引。

最后,关于约束,根据定义,它们与索引无关,但SQL服务器已选择使用索引来实现它们。例如。目前,唯一的约束被实现为索引,但是这可以在未来的版本中改变(尽管我怀疑这会发生)。索引的类型(聚类与否)取决于您,请记住您只能有一个聚簇索引。

如果您还有其他问题,我强烈建议您阅读this book,其中涵盖了这些主题。

0

我没有时间深入回答这个问题,所以这里是我的头顶部的一些信息:

你说得对聚集索引。他们根据聚集索引的排序顺序重新排列物理数据。您可以专门为范围限制查询使用聚簇索引(例如,在日期之间)。

PK默认情况下是聚簇的,但它们不一定是。这只是一个默认设置。 PK应该是该行的UID。

约束可以实现为索引(例如,唯一约束),但也可以实现为默认值。

1

主键是一个逻辑概念在关系数据库理论中 - 这是一个关键(通常也是一个索引),旨在唯一标识您的任何行。因此它必须是唯一的,它不能为NULL。

集群密钥是专门针对SQL Server的存储物理概念。这是一个不仅用于查找等的特殊索引,还定义了表中数据的物理结构。在西欧文化的印刷电​​话簿中(除冰岛外),聚集索引将是“LastName,FirstName”。

由于群集索引定义了您的物理数据布局,您只能拥有其中一个(或者没有 - 不推荐,但是)。

的聚集键

的要求是:

  • 必须是唯一的(如果没有,SQL Server将增加一个4字节的 “uniqueifier”)
  • 应该是稳定的(永不改变)
  • 应尽可能小(INT最好)
  • 应该是不断增加的(认为:IDENTITY)

SQL服务器,使您的主密钥t他默认集群密钥 - 但如果需要,您可以更改密钥。另外,请注意:组成集群密钥的列将被添加到表中每个非聚集索引的每个条目 - 因此您希望尽可能小地保留您的集群关键字。这是因为集群密钥将用于执行“书签查找” - 如果您在非集群索引中找到了一个条目(例如,根据他们的社会安全号码发现某人),现在您需要将整行数据获取更多详细信息,您需要执行查找,为此,使用集群密钥。

有什么牌子好或有用的群集和/或主键的大辩论 - 这里有几个优秀的博客文章来了解这个:

Marc

1

您有几个问题。我会打破其中一些:

当创建索引为什么我应该关心群集与非群集?

有时你会在意如何组织行。这取决于你的数据以及你将如何使用它。例如,如果您的主键是uniqueidentifier,您可能不希望它是CLUSTERED,因为GUID值本质上是随机的。这将导致SQL在整个表中随机插入行,从而导致页面拆分,从而损害性能。如果您的主键值总是按顺序递增(例如,int IDENTITY),那么您可能希望它是CLUSTERED,因此您的表总是会在最后增长。

默认情况下,主键为CLUSTERED,大多数情况下您不必担心它。

有人告诉我,插入和删除非聚集索引很慢,因为树需要“重建”。我认为聚集索引不会以这种方式影响性能?

实际上,情况正好相反。 NONCLUSTERED索引作为单独的数据结构保存,但结构设计为允许进行一些修改而不需要“重新构建”。索引最初创建时,您可以指定FILLFACTOR,该索引指定在索引的每个页面上留出多少可用空间。这允许索引在需要分页之前容忍一些修改。即使在发生页面拆分时,它也只会影响相邻页面,而不会影响整个索引。

同样的行为适用于CLUSTERED指标,但由于CLUSTERED索引存储实际的表数据,对索引页分割操作可以更加昂贵,因为整行可能需要被移动(而不是只对键列和ROWIDNONCLUSTERED索引中)。

FILLFACTOR和页面拆分下面的MSDN页会谈: http://msdn.microsoft.com/en-us/library/aa933139(SQL.80).aspx

有什么特殊的一个主键VS一个聚集唯一索引? 约束与索引有何不同?

对于这两个我认为这是更多关于宣布你的意图。当您致电PRIMARY KEY时,您声明它是识别给定行的主要方法。 PRIMARY KEYCLUSTERED UNIQUE INDEX物理上不同吗?我不确定。行为本质上是一样的,但是对于使用数据库的人来说,您的意图可能并不明确。

关于约束,有许多类型的约束。对于UNIQUE CONSTRAINT,除了声明你的意图之外,它和UNIQUE INDEX之间没有什么区别。还有其他类型的约束不会直接映射到某种索引,如CHECK约束,DEFAULT约束和FOREIGN KEY约束。