在这种情况下哪个索引更好非群集vs群集?

时间:2015-03-06 19:18:48

标签: sql-server clustered-index non-clustered-index

我有一个表有4列(region_id, product_id, cate_id, month_id)作为主键。 此主键是默认创建的,因此为PK创建了聚簇索引。 该表包含超过1000万行。

如果我删除现有的pk并使用非聚集索引类型创建一个新的pk,它对于以下查询是否优于聚集索引?

select region_id, product_id, cate_id, month_id, a, b, c 
from fact_a
where month_id > 100

提前致谢。

2 个答案:

答案 0 :(得分:0)

month_id上的简单非聚簇索引肯定会提高该查询的平均性能(假设大多数行的month_id小于100,因此where子句排除了大多数行)。但是,如果您专门为该查询创建索引(或where子句中包含month_id的任何查询以及a,b,c,month_id或select中的那些查询的子集) ,通过在索引中包含选定的值,您将获得更好的结果,如下所示:

CREATE INDEX index_fact_a_month_id ON fact_a (month_id) INCLUDE (a,b,c)

答案 1 :(得分:0)

快速回答,,删除主键(更多,用一个标识列替换当前的多列主键),然后在Month_ID上创建NCI将更好/更快/效率更高。

聚集索引 - 这是数据。它包含表中每一行的每一列。只能有一个CI,因为表数据只需要存在一次。每行都有一个键......

主键 - 它是识别聚集索引中的行的关键。

非聚集索引 - 它充当聚集索引中行的列子集的表。

保持简单,非聚集索引包含的数据少于聚簇索引,并且它以某种方式(Month_id ASC)对数据进行排序,这使得对它的查询比查询更有效CI(A,B,C,Month_ID)。 SQL Server没有办法“浸入”CI主键或行数据,并说“嘿,我正在按Month_ID过滤,所以我将直接进入该列。”根据群集索引的性质,SQL Server“读取”所有CI行(索引扫描),每列,每个数据字节。非常低效和浪费,因为您的WHERE子句将过滤掉许多这些行。

非群集索引只包含列的子集,因此它更有效,因为它可以说,“嘿,我按Month_ID过滤,我只包含Month_ID,aaannnd Month_ID按升序排列,所以我可以直接跳到我想要的行!“ (索引寻求)。效率更高,因为只有您想要返回的行才会被SQL Server“读取”。

获得更高级的,因为非群集索引只是Month_ID,但是您要查询群集索引中的所有列,SQL Server需要能够返回CI从NCI获得其余的专栏。为此,CI的主键与列子集一起存储在NCI中。因此,NCI实际上就像(Month_ID,CI主键)的两列表。

如果您的主键是怪异的,您的NCI也将是怪异的,因此效率较低(更多的磁盘读取,更多的缓冲池消耗,错误的数据库内容)。

免责声明:可能存在您希望每列都是聚集索引键/ pk的特定方案。我不认为这适用于此,但它是可能的。如果你有一个频繁使用的查询引用where子句或连接的表中的每一列,那么覆盖聚集索引可能是有益的。