如果条件为NULL,那么您将只有一个值的记录集,为什么你需要一个索引到该值?在什么基础上它会做排序?所以,你需要做的过滤索引,其中,processedAt不为空并使用代码条件将有助于
您需要包括ProcessedAt列在创建索引脚本
包列增加一个例子解释@马丁史密斯评论:
表脚本:
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
如果我通过增加甚至+5或10来改变条件,那么它确实keyLookup到聚集索引
select count(id_for_filteredIndex) from TestKeyLookup with(index(NCI_TestKeyLookup))
where another_id > 673110
我试图解释这只是..如果在条件的变化,然后它使用KeyLookup获取。从某种意义上说,如果列是可以空的,并且它是空值,那么它是不同的
你的感觉是正确的。这是没有道理的,不应该逻辑上要求。但这是一个从未被修复的优化器限制。你可以在这里投票https://connect.microsoft.com/SQLServer/feedback/details/454744/filtered-index-not-used-and-key-lookup-with-no-output –
@MartinSmith但是这里的情况是因为ProcessedAt与索引的CreatedAt列不同,为了实现该条件'd.ProccessedAt为null',它必须使用该值。对于该优化器必须执行键查找才能获得适当的值。你提到的错误只有当索引列和谓词列是相同的。我还没有检查行为虽然.. –
不,你已经错过了这一点。它在逻辑上不*具有*进行键查找来获得该列。它正在检查的条件已由过滤的索引条件保证。条件对索引中的所有行都成立。它在逻辑上可以简单地跳过检查它作为OP怀疑。查找的唯一原因是因为优化器当前不包含该逻辑,但它可以并且应该被添加。 –