我有一个相当大的表(5 亿行,30 列宽,总共大约 130 GB 的数据)。该表中的一列是 DateTime 数据类型,我需要在某个日期范围内重复从该表中选择记录。对我来说似乎是过滤索引的好候选人。
这是我的过滤索引:
CREATE NONCLUSTERED INDEX IX_Filtered_Table1_DateField1
ON Table1 (DateField1, PrimaryKeyField)
WHERE (DateField1 >= '2/24/20' AND DateField1 < '4/14/20')
这是我的查询:
DECLARE @MinPrimaryKeyId BIGINT = 2854868995
SELECT TOP 500000 PrimaryKeyField
INTO #Results
FROM Table1 WITH(INDEX(IX_Filtered_Table1_DateField1))
WHERE DateField1 >= '2/24/20'
and DateField1 < '4/14/20'
and PrimaryKeyField > @MinPrimaryKeyId
ORDER BY PrimaryKeyField ASC
在检查执行计划时,我注意到它使用的是我的过滤索引,但它默认为索引扫描操作而不是索引搜索。
如果我尝试使用 FORCESEEK 查询提示(除了我的索引提示),我会收到经典错误:
由于此查询中定义的提示,查询处理器无法生成查询计划
为什么查询处理器无法在该索引上使用 Seek 操作生成执行计划,但它可以使用它执行 Scan 操作?(如果我用 FORCESCAN 切换我的 FORCESEEK 查询提示,它就可以工作,我知道这与在这里根本不使用提示没有什么不同。)
SQL 无法“搜索”,因为此索引的顺序是先按日期,然后按 PrimaryKey。由于您选择的日期与索引的全部内容相匹配,并且 PrimaryKey 没有排序(它们是但仅在每个特定日期内),因此 SQL 必须对其进行扫描。
尝试为此更改索引:
然后 Sql 应该能够使用它(作为日期匹配)并寻找 PrimaryKeyField (并且可能不需要提示,因为这可能是 SQL 无论如何都会决定做的事情)