我有一系列关于 SQL(尤其是 SQL 2005)中的键、索引和约束的问题。我使用 SQL 已有大约 4 年的时间,但我从未能够获得关于这个主题的明确答案,并且博客文章等中总是存在矛盾的信息。我创建和使用的大多数时间表只有一个作为主键的标识列,其他表通过外键指向它。

对于连接表,我没有身份并在外键列上创建复合主键。以下是我目前的信念的一组陈述,可能有错误,如有错误请指正,以及其他问题。

所以这里是:

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

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

我也见过约束,但我从未使用过它们或真正看过它们。有人告诉我,约束的目的是为了增强数据完整性,而索引的目的是为了性能。我还读到,无论如何,约束都被当作索引实现,因此它们是“相同的”。这对我来说听起来不正确。约束与索引有何不同?

有帮助吗?

解决方案

正确地说,

聚集索引是关于如何物理存储表中的数据的定义,即您使用聚类键对B树进行了排序,并且您在叶级别拥有数据。

非聚集索引另一方面是单独的树结构,它们在叶级别只有聚类键(如果表是堆,则是RID),这意味着当你使用非聚簇索引时,你必须使用聚簇索引来获取其他列(除非您的请求完全被非聚集索引覆盖,如果您只请求构成非聚集索引键列的列,则会发生这种情况。)

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

关于性能,更改索引键的插入或更新总是很痛苦,无论它是否是非聚集索引,因为页面拆分可能会发生,这会强制数据在页面之间移动(移动页面)聚集索引会受到更多伤害,因为叶级别中有更多数据)。因此,一般规则是避免更改索引键并插入新值以使它们具有顺序性。否则,您将遇到碎片,并且必须定期重建索引。

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

如果您对此类型有更多疑问,我强烈建议您阅读本书,深入讨论这些主题。

其他提示

您对群集与非群集的假设非常好

似乎主键强制执行非null uniquenes,而唯一索引不强制非null primary vs unique

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

聚类键 是 SQL Server 特有的存储物理概念。它是一个特殊的索引,不仅用于查找等,还定义表中数据的物理结构。在西欧文化的印刷电​​话簿中(冰岛可能除外),聚集索引将是“姓氏,名字”。

由于聚类索引定义了您的物理数据布局,因此您只能拥有其中之一(或没有 - 但不推荐)。

集群键的要求是:

  • 必须是唯一的(如果不是,SQL Server将添加一个4字节的“唯一符”)
  • 应该是稳定的(永不改变)
  • 应尽可能小(INT最好)
  • 应该不断增加(思考:身份)

默认情况下,SQL Server 将主键设为群集键 - 但如果需要,您可以更改它。另外,请注意:组成聚集键的列将添加到表中每个非聚集索引的每个条目中 - 因此您希望使聚集键尽可能小。这是因为聚集键将用于执行“书签查找” - 如果您在非聚集索引中找到了一个条目(例如一个人的社会安全号码),现在您需要获取整行数据以获取更多详细信息,您需要进行查找,为此,使用聚类键。

关于什么才是好的或有用的集群和/或主键存在着激烈的争论 - 这里有一些优秀的博客文章可供阅读:

马克

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

创建索引时,我为什么要关心群集与非群集?

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

默认情况下,主键是 CLUSTERED ,大部分时间你都不用担心。

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

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

同样的行为适用于 CLUSTERED 索引,但由于 CLUSTERED 索引存储了实际的表数据,因此对索引的页面拆分操作可能要贵得多,因为整行可能需要移动(与 NONCLUSTERED 索引中的键列和 ROWID 相比)。

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

主键与群集唯一索引有什么特别之处? 约束如何与索引不同?

对于这两者我认为更多的是宣布你的意图。当您调用 PRIMARY KEY 时,您声明它是识别给定行的主要方法。 PRIMARY KEY CLUSTERED UNIQUE INDEX 在物理上有什么不同?我不确定。行为基本相同,但使用您的数据库的人可能不清楚您的意图。

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top