我可以使用Filtered Index查询"最近修改过的"行

TCC*_*TCC 4 sql sql-server indexing sql-server-2008-r2 filtered-index

我正在使用SQL Server 2008-R2,但我也对更通用的答案感兴趣...

我有一个包含数亿行的表,每行都有一个"DateModified"字段(datetime2(7))

现在,我经常使用类似的查询来轮询该表

select * from table where DateModified > @P1 
Run Code Online (Sandbox Code Playgroud)

这里的参数总是最近的(就像在最后几分钟内一样)并且可能只有少数记录与该值匹配.

我发现我在整个表上维护一个大索引,当我永远不会将索引用于其中的许多值时...所以这听起来像是一个完美的使用Filtered Index我只索引我的行可能会查询...

但在这种情况下,过滤器看起来像什么?我唯一的想法是过滤

where DateModified > [yesterday]
Run Code Online (Sandbox Code Playgroud)

其中[yesterday]是日期文字,但是我必须定期重新定义过滤器,否则过滤器的优势会随着时间的推移而减少.

我一时兴起,ModifiedDate > DATEADD(d,-1,GETDATE())但却给出了一个不起眼的错误......不确定这是怎么回事.

有没有其他方法来实现这一目标?

最后,如果有办法做到这一点,我应该期望统计数据在我的情况下是非常错误的,这会影响我的查询性能吗?

我对这些统计数据的关注来自这篇文章.

我试图通过一些断开连接的数据将更改从一个系统传播到另一个系统...如果您想建议一种完全替代的方法来轮询"DateModified",我很乐意考虑它.

bri*_*ian 6

有一段相似的要求,发现过滤器中不允许使用这些功能.

您可以做的是编写索引脚本并安排它在非高峰时段(可能是夜间)工作.这也将处理统计信息问题,因为每次创建索引时都会重新创建它们.

以下是我们最终做的事情的一个例子:

    CREATE TABLE FilteredTest (
    TestDate datetime
    );
Run Code Online (Sandbox Code Playgroud)

然后按计划运行它以仅使用最新的行创建:

DECLARE @sql varchar(8000) = '

IF EXISTS (SELECT 1 FROM sys.indexes WHERE name = ''IX_FilteredTest_TestDate'')
    DROP INDEX IX_FilteredTest_TestDate ON FilteredTest;

CREATE NONCLUSTERED INDEX IX_FilteredTest_TestDate ON FilteredTest (
    TestDate
)
WHERE TestDate > ''' + CONVERT(varchar(25),DATEADD(d,-1,GETDATE()) ,121) + ''';';

EXEC (@sql);
Run Code Online (Sandbox Code Playgroud)