Sta*_*ite 14 sql sql-server indexing covering-index
我最近在我维护的数据库中遇到了一个索引:
CREATE INDEX [IX_Foo] ON [Foo]
( Id ASC )
INCLUDE
( SubId )
Run Code Online (Sandbox Code Playgroud)
在这种特殊情况下,我遇到的性能问题(Id和SubId上的慢速SELECT过滤)可以通过简单地将SubId列移动到索引中而不是作为包含列来修复.
这让我想到了我根本不理解包含列的原因,一般来说,它们可能只是索引本身的一部分.即使我不特别关心索引本身的项目,在索引中使用列而不是简单地包含列也有任何缺点.
经过一些研究,我发现对索引列中的内容有很多限制(索引的最大宽度,以及一些不能像'image'那样索引的列类型).在这些情况下,我可以看到您将被迫在索引页数据中包含该列.
我唯一能想到的是,如果SubId上有更新,如果包含该列,则不需要重新定位该行(尽管索引中的值需要更改).还有别的东西让我失踪吗?
我正在考虑浏览数据库中的其他索引,并尽可能在索引中包含列.这会是一个错误吗?
我主要对MS SQL Server感兴趣,但也欢迎其他数据库引擎的信息.
到目前为止,答案都是正确的 - 但是它们可能无法传达你从覆盖指数中获得的足够多.
在你的情况下,你有一个表Foo和一些字段,包括一个Id(我假设是主键),以及SubId一些额外的ID.
您还有一个IX_Foo我认为现在只有Id它的索引.
所以现在你需要找到SubIdfor Id=4.
SELECT Id, SubId
FROM Foo
WHERE Id=4
Run Code Online (Sandbox Code Playgroud)
IX_Foo Id=4索引中的值IX_FooSubId,也IX_Foo将包含聚类键值SubId从它这里的要点是:一旦SQL Server找到了你Id=4的IX_Foo索引,它就需要做另一个I/O操作,一个书签查找,去获取整个数据行,以便能够找到该SubId值.
如果您有覆盖索引(例如IX_Foo还包括)SubId,则会消除执行书签查找的额外I/O. 一旦Id=4在IX_Foo索引中找到该值,非聚集索引中的索引页面也将包含值SubId- SQL Server现在可以返回您在SELECT查询中请求的那两个值,而无需额外执行(可能很昂贵和因此,慢速)书签查找只是为了获取另一个Id列.
这是覆盖索引的主要好处 - 如果你只需要一个或两个额外的列,除了你正在进行查找的索引值,通过将这些值包含在索引本身中,你可以节省很多书签查找,从而加快了速度.但是,您应该只包含极少数和少量信息 - 不要将整个数据行复制到所有非聚集索引中!这不是重点.
更新:权衡如下:如果你有一个索引(Id,SubId),索引中的所有页面都有两列 - 整个索引树.
如果包含INCIUDE(SubId),则SubId字段仅出现在叶级别.
这意味着
在索引中有一个附加列的原因是,当您执行仅需要索引使用的列的查询时,您可以自己完成索引中的查询.这样您就可以节省一些时间和资源返回到表中.当发生这种情况时,我们说索引是查询的覆盖索引.
您可能不希望将此附加列作为"索引正确"的一部分的原因是因为当您对该列执行插入或更新时,您更可能需要对索引的某些部分进行重新排序.