优化程序将忽略筛选的索引条件

时间:2012-06-05 12:20:08

标签: sql-server-2008 indexing filtered-index

假设我正在运行一个显示有趣猫图片的网站。我有一个名为CatPictures的表格,其中包含FilenameAwesomenessDeletionDate列以及以下索引:

create nonclustered index CatsByAwesomeness
on CatPictures (Awesomeness) 
include (Filename)
where DeletionDate is null

我的主要疑问是:

select Filename from CatPictures where DeletionDate is null and Awesomeness > 10

作为一个人,我知道上面的索引是SQL Server所需要的,因为索引过滤条件已经确保了DeletionDate is null部分。

然而,SQL Server不知道这一点;我的查询的执行计划不会使用我的索引:

query plan, doing a table scan

即使添加索引提示,它仍会通过查看实际的表数据显式检查DeletionDate

query plan that uses the index, but still does a bookmark lookup

(并且还抱怨缺少包含DeletionDate的索引。)

当然我可以

include (Filename, DeletionDate)

相反,它会起作用:

query plan with the index that includes DeletionDate; this index is used

但是包含该列似乎是浪费,因为这只会占用空间而不添加任何新信息。

有没有办法让SQL Server知道过滤条件已经在检查DeletionDate

3 个答案:

答案 0 :(得分:18)

不,不是。

See this connect item。它是关闭的,因为无法修复。 (或IS NULL具体说明this one

连接项确实提供了如下所示的解决方法。

  

RichardB CFCU发表于29/09/2011 at 9:15 AM

     

解决方法是INCLUDE正在过滤的列。

     

实施例

CREATE NONCLUSTERED INDEX [idx_FilteredKey1] ON [dbo].[TABLE] 
(
    [TABLE_ID] ASC,
    [TABLE_ID2] ASC
)
INCLUDE ( [REMOVAL_TIMESTAMP]) --explicitly include the column here
WHERE ([REMOVAL_TIMESTAMP] IS NULL)

答案 1 :(得分:2)

  

有没有办法让SQL Server知道过滤条件是   已经完成了检查DeletionDate的工作?

没有

过滤的索引旨在解决某些问题,而非ALL。事情在发展,有一天,您可能会看到SQL Server支持您对过滤索引所期望的功能,但您也可能永远看不到它。

有几个很好的理由我可以看到它的工作原理。

改进之处:

  1. 存储。索引仅包含与过滤条件匹配的键
  2. 性能。从上面的一个shoo-in。写得少,页面少=快速检索
  3. 不做的事情:

    1. 从根本上更改查询引擎
    2. 将它们放在一起,考虑到SQL Server是一个高度流水线,多处理器并行能力的野兽,我们在处理查询服务时会遇到以下行为:

      1. 查询优化器选择索引的前提条件:检查Filtered Index是否适用于WHERE子句。
      2. 查询优化器继续正常工作,确定统计选择性,权衡索引 - >书签查找与群集/堆扫描,具体取决于索引是否覆盖等
      3. 将过滤后的索引的条件线程化到查询优化器“核心”中,我怀疑这将比在第1步中留下更大的工作。

        就个人而言,我尊重SQL Server开发团队,如果它很容易,他们可能会把它拉到一个不太遥远的冲刺中并完成它。然而,目前的目标已经实现了它的目的,让我感到非常高兴。

答案 2 :(得分:1)

刚刚发现“功能上的差距”,优化器忽略了过滤的索引,真的很难过。 我想我会尝试使用索引视图,看一下这篇文章

http://www.sqlperformance.com/2013/04/t-sql-queries/optimizer-limitations-with-filtered-indexes