Min*_*ing 0 sql-server-2008 sql-server optimization query-performance
我有一张具有以下结构的表,如您所见,有一个聚集索引和两个非聚集索引,一个非聚集索引是 IX_ParentId_Include,另一个是 FLIX_ParentId_Include
除了第二个索引被过滤之外,它们是相同的。
CREATE TABLE [dbo].[PhotoRepo] (
[PhotoRepoId] INT IDENTITY (1, 1) NOT FOR REPLICATION NOT NULL,
[TypeId] TINYINT NULL,
[ParentId] INT NULL,
[RemoteLocation] VARCHAR (4000) NOT NULL,
[UploadedAt] DATETIME NOT NULL,
[UploadedBy] VARCHAR (255) NULL,
[FileSize] INT NOT NULL,
[DefaultChild] BIT NOT NULL,
[RemoteLocationUploadedAt] DATETIME NULL,
CONSTRAINT [PK_FileList] PRIMARY KEY NONCLUSTERED ([PhotoRepoId] ASC)
);
GO
CREATE CLUSTERED INDEX [IX_PhotoRepoId]
ON [dbo].[PhotoRepo]([PhotoRepoId] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_ParentId_Include]
ON [dbo].[PhotoRepo]([ParentId] ASC)
INCLUDE([RemoteLocation], [DefaultChild], [TypeId]);
GO
CREATE NONCLUSTERED INDEX [FLIX_ParentId_Include]
ON [dbo].[PhotoRepo]([ParentId] ASC)
INCLUDE([RemoteLocation], [DefaultChild], [TypeId])
WHERE TypeId <> 7;
GO
Run Code Online (Sandbox Code Playgroud)
现在,当我在启用执行计划的情况下运行此查询时,查询优化器不使用过滤器索引,我希望它应该更有效,它使用 IX_ParentId_Include。仅当我强制它或删除 IX_ParentId_Include 时,它才使用过滤器索引
有谁知道为什么?
SELECT
*
FROM PhotoRepo
WHERE
typeid <> 7 and
parentid = 123
Run Code Online (Sandbox Code Playgroud)
PS:有 30% 的行 typeid = 7
为什么你认为它应该使用过滤索引?您已SELECT *
在查询中使用,并且您的谓词不仅仅涉及过滤条件。SQL Server 将不得不在覆盖它的另一个索引中查找这些列(您的SELECT *
计划应该包括一个键查找来检索这些其他列)。
SQL Server 将根据统计信息/基数(例如,当前有多少行与过滤器匹配,总共有多少行)来决定它应该使用哪个索引。在这种情况下,它可能是抛硬币,因为它可以查找与ParentId
谓词匹配的 19 行,并且这样做不会花费更多的 I/O。如果它代表表中比 30% 小得多的部分,它可能会选择过滤索引。但是,如果您添加OPTION (RECOMPILE)
到查询中,您应该会看到它的作用。根据您的参数化设置,它可能正在使用以不同参数值(例如,与索引过滤器不匹配的参数值)缓存的计划。
在这种情况下,我相信您会看到这种行为,因为 RTM。请安装Service Pack 3并考虑累积更新 16。我快速浏览并没有看到任何与过滤索引相关的内容,但这可能是其他一些优化器不稳定的副产品,同时已修复。无论如何,我实在想不出有什么好的理由让您此时继续运行 RTM。
也可能与这些其他“已知功能缺陷的错误”有关:
我还写了一篇关于过滤索引的一系列限制的博客,并指出了大量相关的 Connect 项目。其中大部分仍未修复,并且在大多数情况下,过滤索引自首次引入以来就完全没有受到关注。如果您打算使用这些对象,并希望使用它们来加速您的查询,那么您最好熟悉所有这些限制,并考虑使用索引提示来强制在某些情况下使用它们。场景。使用索引提示的注意事项,当然: