为什么不使用 IS NULL 值上的过滤索引?

jer*_*ech 23 performance sql-server index-tuning filtered-index query-performance

假设我们有一个像这样的表定义:

CREATE TABLE MyTab (
    ID INT IDENTITY(1,1) CONSTRAINT PK_MyTab_ID PRIMARY KEY
    ,GroupByColumn NVARCHAR(10) NOT NULL
    ,WhereColumn DATETIME NULL
    )
Run Code Online (Sandbox Code Playgroud)

还有一个过滤的非聚集索引,如下所示:

CREATE NONCLUSTERED INDEX IX_MyTab_GroupByColumn ON MyTab 
    (GroupByColumn)
WHERE (WhereColumn IS NULL) 
Run Code Online (Sandbox Code Playgroud)

为什么这个索引没有“覆盖”这个查询:

SELECT 
    GroupByColumn
    ,COUNT(*)
FROM MyTab
WHERE WhereColumn IS NULL
GROUP BY GroupByColumn
Run Code Online (Sandbox Code Playgroud)

我得到这个执行计划:

在此处输入图片说明

KeyLookup 用于 WhereColumn IS NULL 谓词。

这是计划:https : //www.brentozar.com/pastetheplan/?id=SJcbLHxO7

Dav*_*oft 27

为什么这个索引没有“覆盖”这个查询:

没有很好的理由。这是该查询的覆盖索引。

请在这里为反馈项目投票:https : //feedback.azure.com/forums/908035-sql-server/suggestions/32896348-filtered-index-not-used-when-is-null-and-key-looku

作为一种解决方法,包括WhereColumn在过滤索引中:

CREATE NONCLUSTERED INDEX IX_MyTab_GroupByColumn 
ON MyTab (GroupByColumn) include (WhereColumn)
WHERE (WhereColumn IS NULL) 
Run Code Online (Sandbox Code Playgroud)

  • 这是 Gail Shaw 十多年前[报道](http://connect.microsoft.com/SQLServer/feedback/details/454744)。然后连接死了。我现在能找到的最接近的是 https://feedback.azure.com/forums/908035-sql-server/suggestions/32896348-filtered-index-not-used-when-is-null-and-key-looku (14认同)

小智 5

我在几周前做一些测试时遇到了同样的问题。我有一个带有主谓词的查询,它要求返回的结果有一个 NULL 关闭时间,我考虑使用过滤索引,因为 25K 的 2M+ 记录是 NULL,这个数字很快就会减少。

过滤后的索引没有被使用——我认为是由于“非唯一性”或共性——直到我找到了一篇 Microsoft 支持文章,上面写着:

要解决此问题,请在返回的列中包含测试为 NULL 的列。或者,将此列添加为索引中的包含列。

因此,将列添加到索引(或包含)似乎是 MS 的官方回应。