为什么在SQL索引中使用INCLUDE

前端之家收集整理的这篇文章主要介绍了为什么在SQL索引中使用INCLUDE前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我最近在数据库中遇到了一个索引,它的形式是:
CREATE INDEX [IX_Foo] ON [Foo]
( Id ASC )
INCLUDE 
( SubId )

在这种特殊情况下,我遇到的性能问题(对Id和SubId都是缓慢的SELECT过滤)可以通过简单地将SubId列移动到索引中而不是包含列来修复.

这让我想到,我不明白背后的推理包括列,一般来说,它们只能是索引本身的一部分.即使我不特别关心索引中的项目本身,在索引中列出列表,而不仅仅是被包含在内.

经过一些研究,我知道对索引列(最大的索引宽度,以及一些无法索引的列类型,如“image”)可以进行一些限制.在这些情况下,我可以看到您将被迫将列添加到索引页数据中.

我唯一可以想到的是,如果在SubId上有更新,如果列被包括(尽管索引中的值需要更改),该行将不需要被重新定位.还有什么我失踪的吗?

我正在考虑通过数据库中的其他索引,并尽可能地在索引中包括列.这会是一个错误吗?

我主要对MS sql Server感兴趣,但也欢迎有关其他DB引擎的信息.

解决方法

迄今为止的答案都是正确的,全部的 – 但是它们可能不足以表达你从覆盖索引中获得的东西.

在你的情况下,你有一个表Foo和一些字段,包括一个Id(我认为是主键)和一个SubId,这是一些额外的ID.

你也有一个索引IX_Foo,我假设现在只有Id.

所以现在你需要找到IdId 4的SubId.

SELECT Id,SubId
FROM Foo
WHERE Id=4

> sql Server将查看SELECT语句并确定它可以使用IX_Foo
>然后,您将在索引IX_Foo中搜索值Id = 4
>当它找到它时,它现在也需要SubId的值
>非聚集索引IX_Foo将包含聚类键值
>使用该集群密钥值,sql Server将执行“书签查找”以查找整个数据行所在的实际数据页面
>它将获取页面并从中提取SubId的值
>它将返回这些值以满足您的查询

这里的要点是:一旦sql Server在IX_Foo索引中找到您的Id = 4,那么它将需要执行另一个I / O操作(书签查找)来获取整个数据行,以便能够找到SubId值.

如果您有覆盖索引,例如IX_Foo还包括SubId,消除了额外的I / O来进行书签查找.在IX_Foo索引中找到值Id = 4之后,非聚集索引中的索引页面也将包含SubId的值 – sql Server现在可以在SELECT查询中返回您要求的两个值,而无需执行额外的(潜在的昂贵和因此缓慢)书签查找只是为了获取另一个Id列.

这是覆盖索引的主要优点 – 如果您只需要一个或两个额外的列,除了您正在进行查找的索引值之外,通过将这些值包含在索引本身中,您可以自行保存很多书签查找,因此快速的事情显着.但是,您应该只包含很少的信息,而不是将整个数据行重复到所有非聚集索引中!这不是重点.

更新:权衡是这样的:如果您有一个索引(Id,SubId),索引中的所有页面都有两列 – 整个索引树.

如果您使用INCLUDE(S​​ubId),SubId字段仅存在于叶级别.

意即

> sql Server无法在SubId上进行搜索和比较(值不在索引树中)>使用更少的空间,因为值仅在叶级别

猜你在找的MsSQL相关文章