我昨天试图对过滤索引进行一些测试并创建了一个相当简单的情况:
CREATE TABLE IndexTest
(
ID INT NOT NULL IDENTITY(1,1) CONSTRAINT pk_IndexTest PRIMARY KEY,
Col1 CHAR(1)
)
GO
CREATE INDEX ix_IndexTest ON IndexTest(Col1)
WHERE Col1 IS NOT NULL
GO
INSERT INTO IndexTest VALUES ('A'),('B'),('C'),('D')
INSERT INTO IndexTest VALUES (''),(''),(''),('')
INSERT INTO IndexTest VALUES (NULL),(NULL),(NULL),(NULL)
GO
然后我尝试使用提示运行以下查询以强制它使用过滤索引。
SELECT *
FROM IndexTest WITH (INDEX(ix_IndexTest))
GO
但我不断收到错误:
由于此查询中定义的提示,查询处理器无法生成查询计划。在不指定任何提示且不使用 SET FORCEPLAN 的情况下重新提交查询。
如果我删除过滤器而不是它,它会起作用。我什至尝试以各种方式更改过滤器,例如WHERE Col1 = ''
等。每当我有过滤器时,我都会收到该错误。谁能告诉我为什么?难道我做错了什么?
我在 SQL Server 2012 和 2014 实例上进行了尝试,并在此处创建了它的 sqlfiddle:
http://www.sqlfiddle.com/#!6/4a850/1
编辑:不确定这是否重要,但具体来说,我想看看我是否能看到索引实际包含了哪些行。这个想法来自于看到有人使用这种技术从损坏的表中恢复数据(使用未过滤的索引)。
断开连接可能是过滤索引不会自动为您过滤结果 - 您必须编写一个与索引的过滤谓词匹配的 WHERE 子句才能使用索引。
换句话说,如果您只是想获取行数
WHERE Col1 IS NOT NULL
,您仍然需要一个WHERE
子句来限制行数。如果 SQL Server 不能使用您试图强制满足查询返回的所有行的索引,它不能通过索引持有比表更少(或相同*)行的定义来做到这一点,它无法运行。如果由于基础表/CI 已损坏而试图从非聚集索引中查找数据,那么
DBCC IND/PAGE
使用十六进制编辑器 Paul Randal 模拟可能会好运。