优化器忽略过滤的索引条件
Posted
技术标签:
【中文标题】优化器忽略过滤的索引条件【英文标题】:Filtered index condition is ignored by optimizer 【发布时间】:2012-06-05 12:20:08 【问题描述】:假设我正在运行一个显示有趣猫图片的网站。我有一个名为CatPictures
的表,其中包含Filename
、Awesomeness
和DeletionDate
列,以及以下索引:
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 不知道这一点;我的查询的执行计划不会使用我的索引:
即使添加索引提示,它仍然会通过查看实际表数据来显式检查DeletionDate
:
(此外还抱怨缺少包含DeletionDate
的索引)。
当然可以
include (Filename, DeletionDate)
相反,它会起作用:
但是包含该列似乎是一种浪费,因为这只会占用空间而没有添加任何新信息。
有没有办法让 SQL Server 知道过滤条件已经在执行检查 DeletionDate
的工作?
【问题讨论】:
表中有多少数据。有时,对于少量数据,SQL 会进行表扫描,因为它更有效。这与运营效率有关。 sql 保留的统计信息可能会强制进行表扫描。 你的表有多少行? SQL Server 有时更喜欢对选择性较低的小表或索引进行表扫描。 @Namphibian 我在空表和 500 万行的表中看到了同样的情况。 【参考方案1】:不,目前没有。
See this connect item。它因无法修复而关闭。 (或 this one 专门针对 IS NULL
案例)
connect 项确实提供了如下所示的解决方法。
RichardB CFCU 于 2011 年 9 月 29 日上午 9:15 发布
解决方法是
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)
【讨论】:
还有这个,它不是“错误”,而是“功能差距”。 SQL Server 团队什么时候变成了一群政客? connect.microsoft.com/SQLServer/feedback/details/454744/… 这太糟糕了,但我想没有比这更权威的了。谢谢。 功能上的差距 = 无用的功能。 @Namphibian 仅当您的用例达到差距时。在未出现此问题的情况下,我使用过滤索引对系统进行了一些重大改进。 @Aaron 更多的是关于如何将非常有用的功能标记为不是真正问题的评论。你会期望像微软这样的大企业会做一些事情而不是掩盖它。过滤索引很棒......大多数时候。【参考方案2】:有没有办法让 SQL Server 知道过滤条件是 已经完成检查删除日期的工作了吗?
没有。
过滤索引旨在解决某些问题,而不是全部。随着事情的发展,总有一天,您可能会看到 SQL Server 支持您期望的过滤索引功能,但也有可能您永远看不到它。
我可以看到它的工作原理有几个很好的理由。
改进的地方:
-
存储。索引只包含匹配过滤条件的键
性能。从上面的一个嘘声。更少的写入和更少的页面 = 更快的检索
它没有做什么:
-
彻底改变查询引擎
将它们放在一起,考虑到 SQL Server 是一个高度流水线、多处理器并行能力的野兽,我们在处理查询服务时会得到以下行为:
-
查询优化器选择索引的前提条件:检查过滤索引是否适用于 WHERE 子句。
查询优化器继续正常工作,从统计数据中确定选择性,权衡索引->书签查找与集群/堆扫描,具体取决于索引是否覆盖等
我怀疑将过滤索引的条件线程化到查询优化器“核心”中,这比将其留在第 1 步要大得多。
就个人而言,我尊重 SQL Server 开发团队,如果它足够简单,他们可能会将其拉入一个不远的冲刺并完成它。但是,目前的情况已经达到了预期,让我很高兴。
【讨论】:
【参考方案3】:刚刚发现“功能上的差距”,过滤索引被优化器忽略真的很遗憾。 我想我会尝试使用索引视图,看看这篇文章
http://www.sqlperformance.com/2013/04/t-sql-queries/optimizer-limitations-with-filtered-indexes
【讨论】:
以上是关于优化器忽略过滤的索引条件的主要内容,如果未能解决你的问题,请参考以下文章