2011-03-25 126 views
2

嗨,我是新来的SQL,我想知道如果有人可以告诉我在同一列使用群集和非集群索引。我在我的工作中查看了一些表脚本,但不明白在一列上同时使用了集群索引和非集群索引的用途。它是一个ID列,它位于数据库中的所有表中。索引问题

+0

假设您正在谈论SQL Server,我们是否正确? – 2011-03-25 20:51:01

+0

是的sql,谢谢... – Programmer 2011-03-25 20:56:27

+1

'SQL'只是**结构化查询语言** - 它不是**产品** - 没有数据库系统。你指的是微软的** SQL Server ** - 一个具体的数据库产品。 – 2011-03-25 21:19:43

回答

2

在一个非常简单的术语中,CLUSTERED和NON CLUSTERED INDEX之间的区别在于,CLUSTERED索引是表中记录的物理顺序,基于索引字段中的值,而非CLUSTERED索引是逻辑根据索引字段中的值排序表中的记录。这个逻辑顺序是由SQL数据库引擎根据表中值的统计分布决定的。

另一个重要的区别是,对于一个表,只能有一个CLUSTERED索引(因为它是存储在该表中的数据的物理顺序)。虽然您可以在同一个表上的不同字段上有许多不同的非聚簇索引。

就这么说,当然你可以在表的同一个字段上同时使用CLUSTERED和NON CLUSTERED索引,这很有用,因为通常CLUSTERED索引特别擅长顺序访问数据,而非CLUSTERED索引可以针对随机进行优化SQL数据库引擎访问数据。通过这种方式,同一列上的CLUSTERED和NON CLUSTERED索引组合使您能够在基于索引字段中的值进行搜索时高度优化对该表中记录的访问。

+0

这并不能解释为什么你会在同一列上有NCI和CI。这两个索引的非叶级页面几乎是相同的,所以当用特定的id查找时,对随机访问没有特别的好处(特别是考虑到NCI使用CI键作为行定位器,所以CI将* *仍然**必须被遍历!)。也不保证它们是物理顺序(碎片)。它们都是按照逻辑顺序排列的,下一页和上一页由页头中的字段表示。 – 2011-03-27 00:59:51

+0

@Martin在NCI/CI情况下,通过一个ID查找单个行几乎没有什么区别。在这种情况下,如果ID列在数据库的所有表中,可能是错误的或者它可能是正确的,很难知道这些ID是否代表相同的事情。这听起来像是一种代码味道,但也有合法的原因。如果OP忽略NCI包含列(并且它成为特定查询的覆盖范围),该怎么办?然后,NCI扫描可能会优先于此表上的表扫描。 – 2011-03-27 13:48:24

+0

@Cade - 是的,这是真的。我注意到我原来的评论中有一个错误。非叶页当然不会像CI那样可能有更多的页面,所以树会越来越深,但是NCI的任何查找都不得不遍历CI。 – 2011-03-27 13:53:41

4

聚集索引并不是一个真正的索引 - 从某种意义上说,它是根据键在树中组织的所有数据。

非聚集索引只是树中的关键字,其中包含任何附加的列以及必要的书签,以便在必要时进入数据行。数据本身可以存储在聚簇索引或堆中。可以有许多非聚集索引,但显然只有一种真正的选择来存储数据的方式。

对于特定查询的执行情况,堆上的覆盖非聚簇索引(或任何,无关紧要,因为索引正在覆盖)通常可以轻松地胜过聚簇索引,因为索引可能适合更多每页行数,并且不需要书签查找就可以将数据从行中取出,而聚集索引seek/scan将读取并丢弃更多数据,并且每页的行数更少。

通常,您需要聚簇索引,并且聚簇键应该是窄的,静态的,增加的,唯一的。

但是,对于查询性能,您真的想查看非聚簇索引,并选择覆盖并在适用的情况下将正确方向的排序顺序。

+0

你还没有给出任何用例,说明你为什么在一个'id'列上有一个NCI和一个CI。我可以想象一个'id'上的狭窄索引可能对某些类型的查询很有用,比如半连接,或者强制外键约束 - 不能真的想到其他用例吗? – 2011-03-27 01:06:11

+0

@Martin一个具有单个id且不包含列的NCI仍然会更快地进行存在验证,然后是id上的配置项,因为每个页面都会包含更多数据(假设表格相对较宽)。但是,你是对的,这种情况只适用于id是外键的情况,例如FK到符合特定条件的行的另一个表。一般来说,被覆盖的NCI将是首选。在这种情况下,书签和CI的选择是无关紧要的,因为索引覆盖。当然,你应该有一个CI,但不要依赖它来读取性能。 – 2011-03-27 13:40:52