【问题标题】:Can I use a Filtered Index for querying "recently modified" rows我可以使用过滤索引来查询“最近修改”的行吗
【发布时间】:2013-09-09 22:30:11
【问题描述】:

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

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

现在我经常使用类似

的查询来轮询该表
select * from table where DateModified > @P1 

这里的参数总是最近的(比如最近几分钟内),并且可能只有少数记录匹配该值。

我突然想到我在整个表上维护一个大索引,而我永远不会将索引用于许多这些值......所以这听起来像是过滤索引的完美使用,我只索引我可能会查询的行...

但在这种情况下,过滤器会是什么样子?我唯一的想法是过滤

where DateModified > [yesterday]

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

一时兴起,我尝试了ModifiedDate > DATEADD(d,-1,GETDATE()),但出现了一个无法描述的错误……我不确定这怎么可能。

还有其他方法可以做到这一点吗?

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

我对统计数据的担忧来自this article

我正在尝试使用一些断开连接的数据将更改从一个系统传播到另一个系统...如果您想建议一种完全替代的方法来轮询“DateModified”,我很乐意考虑。

【问题讨论】:

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


    【解决方案1】:

    前段时间有类似需求,发现过滤器中不允许使用函数。

    您可以做的是编写索引并安排它在非高峰(可能是夜间)时间在作业中运行。这也将解决统计问题,因为每次创建索引时都会重新创建它们。

    下面是我们最终做的一个例子:

        CREATE TABLE FilteredTest (
        TestDate datetime
        );
    

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

    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);
    

    【讨论】:

    • 如果你 declared a length for your varchar,我会 +1。
    • 你去@AaronBertrand。同意最佳做法。
    • @brian 感谢您根据您的经验分享过滤索引的最佳实践...我在处理更改时清除了一个单独的表。对你来说,这听起来像是一个合理的想法吗?它还有一个额外的好处是能够从相关表中记录已删除的行。我真的只需要记录更改/添加/删除行的 ID(我正在记录一个日期时间和“更改类型”以及良好的衡量标准)
    • 澄清我之前的评论......这个日志记录将通过触发器完成
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    相关资源
    最近更新 更多