2011-07-01 33 views
2

比方说,我有一个表是这样的:索引是否已涵盖群集主键?

CREATE TABLE t(
    [guid] [uniqueidentifier] NOT NULL, 
    [category] [nvarchar](400) 
    {,...other columns} 
) 

哪里​​是我的主键,并有一个聚集索引。

现在,我想的是涵盖category和​​,因为我卷起按类别相关t一些其他的东西的指标,我想避免包括t表本身。

是否足以创建包含category的索引,还是我还需要包含​​?

我希望SQL Server索引到t直接指向页面偏移,而不是简单地指的是​​主键值,这意味着我将需要明确包括PK列,以避免触及t。是这样吗?

回答

2

其实你的假设是错误的 - 所有SQL Server非聚集索引不包括聚集键(单个或多个列),并直接在某个物理页做点。

这可以防止SQL Server在需要将页面拆分为两个或重新定位时必须重新组织和更新大量索引条目。因此,如果您在非聚集索引中寻找并找到一个值,那么您拥有集群键,SQL Server将需要执行“书签查找”(或键查找)来检索实际数据页面(叶页在聚类索引中)来获取属于单个行的整个数据集。这说 - 如果你曾经有过一种情况,它取决于键列的排序,那么你仍然可能需要在(guid, category)上专门创建一个索引 - 当然,在这种情况下,SQL Server足够智能弄清楚聚类键列已经在索引中,并且不会再增加一次。

聚簇密钥列包含在每个非聚簇索引中这一事实是另一个强大的原因,为什么你的聚簇键应该是狭窄的,静态的和唯一的。使它们太宽(超过8字节的任何内容)是一个膨胀和减速的肯定配方。

+0

谢谢Marc!我以为我会疯狂地解释执行计划。有意义的是,索引不应该与页面指针混杂在一起,即使避免书签查找的性能优势很小。有关订购的好处。 – richardtallent

1

与marc_s的答案略有不同。

(类别,guid)上的覆盖索引在GUID与主键排序上有不同的排序。因此,guid可能在索引中出现两次,因为它位于键列列表中,并且指向聚簇索引。

如果您包含(作为非键列),guid SQL Server将不会再次添加它。

刚才我无法测试关键列的东西,但是我在SQL Server 2005上已经验证了INCLUDE一个。