为什么覆盖过滤索引执行查找

时间:2016-09-21 17:32:14

标签: sql-server lookup filtered-index

我有一张桌子,当总数大于数字时,需要检查每一分钟以提醒。

 SELECT 
  count(CreatedAt) Total
 FROM 
  Process d 
 WHERE 
  d.ProcessedAt is null
  AND DATEDIFF(second, GETUTCDATE(), d.CreatedAt) > 30

我的想法是创建一个过滤索引,例如:

CREATE NONCLUSTERED INDEX [FIX_Process_CreatedAt_ProcessedAt] ON [dbo].[Process]
(
    [CreatedAt] ASC
)
WHERE ProcessedAt IS NULL

但是看一下执行计划,有一个关键的查找。

我不明白为什么,因为索引有两列用于查询。

任何人都可以解释我为什么吗?

1 个答案:

答案 0 :(得分:1)

如果条件为NULL,那么您将只有一个记录集值以及为什么需要该值的索引?它将在什么基础上进行排序?因此,您需要执行过滤索引,其中processedAt不为null,并在代码中使用该条件将有助于

您需要在创建索引脚本

中的INCLUDED列中包含ProcessedAt列

添加一个例子来解释@Martin Smith的评论:

表脚本:

Create Table TestKeyLookup
(
id int identity(1,1) primary key -- Created PK which will create clustered Index
,id_for_filteredIndex int NOT NULL
,another_id int NOT NULL
)

插入表记录:

declare @i int = 50
while @i < 1000000 
begin
    insert into TestKeyLookup (id_for_filteredIndex, another_id) values (@i, @i+5)
    set @i = @i + 10
END

在id_for_FilteredIndex列上创建非群集过滤索引,条件位于不同列another_id

create nonclustered index NCI_TestKeyLookup on dbo.TestKeyLookup(id_for_filteredIndex)
where another_id > **673105**

如果我使用完全相同的条件查询表,则优化器不使用KeyLookup

select  count(id_for_filteredIndex) from TestKeyLookup with(index(NCI_TestKeyLookup))
where another_id > 673105

It does use filtered index

如果我通过增加偶数+5或10来改变条件,那么它会将keyLookup改为聚集索引

select  count(id_for_filteredIndex) from TestKeyLookup with(index(NCI_TestKeyLookup))
where another_id > 673110

Different Id where another_id is greater than filtered index condition

我试图解释这个..如果条件有变化,那么它使用KeyLookup来获取。在某种程度上,如果列可以为空并且它具有空值,则它是正确的,那么它是不同的