SQL Server 2008非聚簇索引是否包含聚簇索引字段?

时间:2011-01-02 16:30:10

标签: sql sql-server-2008 indexing clustered-index

好的,我需要再次拼出这个。我已经在线阅读了这些文章,但我还没有找到明确的答案。

在SQL Server 2008中,我有一个“核心”表,其中包含大约50,000条记录和大量读取活动,在所有查询中以相同的方式使用。此数据每月更新一次,每秒读取数百次。

数据在字段上具有聚簇索引,因为它们经常被访问。假设聚集索引是:

CLUSTERED INDEX

Field1 int
Field2 int
Field3 int
Field4 int
Field5 int

现在,没有比这更多的数据了,所以将额外的几列放入“包含的列”是有意义的,但是SQL Server不允许在聚集索引上包含列。 / p>

因此,我们有第二个索引,其字段与Clustered Index基本相同,其他列为“Included Columns”。但是,从我读过的内容来看,我认为这可能是多余的?

COVERING INDEX(非群集)

Field1 int
Field2 int
Field3 int
Field4 int
Field5 int

包含栏目

Field6 varchar(96)
Field7 varchar(96)

非聚集索引ALREADY是否具有其中定义的聚簇索引的列?

如果是这样,那么如何使用NO列创建第二个索引(除了已经在聚簇索引中的内容)?换句话说,我想说“这个索引与聚集索引完全相同......带有几个包含的列”。

或者,将所有列放入聚集索引(包括不识别记录的两个列)会更好吗? varchar列确实更频繁地更新(每天几次而不是每月一次),所以我希望将它们保留在聚集索引之外,但我认为它们足够深,它们不会影响索引树足以在发生更改时导致任何重新平衡。

那么,有没有一种有效的方法来设置这些索引,以便通过索引可以获得该表的所有列而无需返回到表中?

4 个答案:

答案 0 :(得分:5)

是 - NonClustered Index通过群集密钥访问表中的数据(当表具有群集密钥时,以及当没有群集密钥时访问行ID),因此它将自动包含聚集索引字段。这也是为什么更改聚簇索引会强制重建所有非聚集索引的原因。

如果该索引满足大量查询,则包含2个字段的附加NC索引可能有效,但我不确定是否正在解决正确的问题。

在Clustered Key中包含2个以上的字段并不理想,现在在NC索引中确认,您可以看到该表上的每个索引都包含其中的每个索引的群集密钥。

这是您希望群集密钥尽可能缩小的主要原因,如果有的话,您应该检查群集密钥,然后询问您选择5字段群集密钥的原因,并且该选择是否会导致碎片化?

使用群集密钥的人工值(Identity)可能会更好,并使用唯一的NC索引来强制使用5字段聚类密钥的唯一性。

答案 1 :(得分:4)

聚集索引不需要包含。包括在索引树的最低级别存储额外数据的方法。此聚簇索引中的数据。所以你不需要重叠索引

但是,如果您担心内存占用,则需要缩小表格。有了50k行,我会考虑从-32768开始的smallint代理键。然后,删除每个NC索引中C键的开销。这意味着您可以在问题中提到覆盖索引。

请注意,一旦您的执行计划被缓存并且数据位于缓存中,那么您的查询将来自内存。您的使用意味着它将在缓存中保留一段时间。缺少更新意味着您将无法获得统计驱动的重新编译。

但是,如果您的数据几乎是静态的,那么如果性能受到关注,为什么还要调用SQL Server呢?缓存它。根据我的缓存注释删除网络往返,这可能是您最大的开销。  我们将一些查找和缓存外包给我们的客户端以减少服务器负载(我们在峰值负载下大约20秒内有50k写入)

答案 2 :(得分:1)

  

这是有道理的   只是把额外的几个   列包含在“包含的列”中,但是   SQL Server不允许包含   聚集索引上的列

包含额外列是不可能的,因为聚簇索引已包含所有列。这就是索引被称为聚集的原因。

  

所以,我们有第二个索引   与...基本相同的字段   聚集索引,与另一个   列为“包含的列”。   但是,从我读过的内容来看,我   相信这可能是多余的?

是的,这可能是多余的。有一些罕见的例外,聚集索引不适合内存。

  

非聚集索引是否已成立   拥有群集中的列   在其中定义的索引?

可能:非聚集索引包含指向聚簇索引的指针。如果聚簇索引是唯一的,则此指针由所有聚簇索引字段组成。 (在大多数情况下,这些字段与主键对应。)

  

那么,有没有一种有效的设置方法   这些索引就这样全部了   该表的列可用   通过索引而不回头   到桌子?

在发布的示例中,看起来聚簇索引就足够了,并且您不需要任何其他索引来避免表查找。您可以通过运行查询并查找“密钥查找”或“清除查找”操作来验证这一点。

答案 3 :(得分:1)

我认为您需要更好地了解CLUSTERED和NONCLUSTERED索引。聚簇索引是平衡树(B树),其中每个节点包含索引的键列。通常,通常是最佳选项,一列是索引的关键列。每行的所有数据都存储在聚集索引的叶级(即底层)。这就是为什么你不能在聚簇索引中包含列;所有列都包含在定义中。

非聚集索引也是B树结构。每个节点都包含索引的键列。非聚集索引的叶级别包含任何包含的列。请注意,键列和包含列之间的区别在于键列值出现在索引的每个级别,而包含的列仅出现在叶级别。叶级别还包含聚集索引中的键列,用于将索引链接到表数据。

您在任何索引中包含的列越多,索引就越大。而且,这会降低性能。

因此,对于聚簇索引,您不需要将所有列,甚至许多列都包含在索引中作为键。数据已经是索引的一部分。