SMS 建议覆盖索引中的所有列?

Jos*_*eld 6 index sql-server t-sql

我对索引和数据库工作仍然有点新,所以我很可能会遗漏一些明显的东西。

SMS 建议在我的一个表中添加一个覆盖索引,我认为该列上的索引非常有意义。但是,它还建议在表中每隔一列包括(覆盖)。对我来说,这似乎是将整个表移动到索引中。我认为这可能是一个坏主意。在这种情况下,SMS 是否可能误导我?

更一般地说,是否有任何理由覆盖表中的每一列?

SELECT  * 
    FROM    SlideshowImages SI
    JOIN    Files F ON F.PK_FileID = SI.FK_FileID
    WHERE   F.FK_ModuleID   = 81
    AND     F.ParentType    = 2
    AND     F.FK_ItemID     = @SlideshowID
    ORDER BY F.[Order] ASC
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

SMS 的建议索引 - SlideshowImages 表的所有 10 列:

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[SlideshowImages] ([FK_FileID])
INCLUDE ([PK_SlideshowImageID],[Title],[Caption],[IsLink],[LinkAddress],[StartDate],[EndDate],[AltText],[OpenInNewWindow])
Run Code Online (Sandbox Code Playgroud)

Pau*_*ite 5

SMS 建议在我的一个表中添加一个覆盖索引,该索引对我认为非常有意义的列进行索引。但是,它还建议在表中每隔一列包括(覆盖)。

SSMS 中显示的建议实际上是由查询优化器在搜索查询的有效物理执行计划时生成的。这些建议是机会主义的,并且仅基于对单个查询的表面分析。

对我来说,这似乎是将整个表移动到索引中。

复制而不是移动,但是是的,覆盖基表中每一列的索引(作为键或包含的列)本质上是以不同方式排序的表数据的副本。从概念上讲,这与在表上具有多个聚集索引相同。

更一般地说,是否有任何理由覆盖表中的每一列?

这样做很不寻常,但总会有非常具体的场景可以有意义。以不同方式排序的表数据副本的索引将需要针对基表的每次更改进行维护,将消耗更多的磁盘和内存空间,并会生成更多的事务日志。对于大多数应用程序,成本大于收益。

添加索引的时间从平均70毫秒5.8 毫秒(包括所有列)和7 毫秒,仅包含索引且没有覆盖的列(5 次试验;客户端统计)。所以似乎覆盖所有更快。

完全覆盖索引意味着查询所需的所有数据都可以来自该单个 b 树结构。如果非聚集索引没有完全覆盖查询,优化器可以选择使用索引定位行,然后使用存储在非聚集索引中的行定位器在基表中查找剩余的列数据。额外的步骤有一个与之相关的成本,它与索引键搜索限定的行数成正比。

在大多数情况下,FK_FileID单独创建非聚集索引提供的性能改进将被认为是各种考虑因素之间的最佳权衡。也就是说,您可能有非常具体的要求,这意味着您很乐意选择完全覆盖的选项。