带有时间戳和变量的 SQL Server 查询性能

Posted

技术标签:

【中文标题】带有时间戳和变量的 SQL Server 查询性能【英文标题】:SQL Server Query Performance with Timestamp and variable 【发布时间】:2015-08-31 11:42:28 【问题描述】:

我有一个简单的 SQL 查询来计算过去 24 小时内客户端的遥测记录数。

使用 TimeStamp 上的索引,以下查询在不到 1 秒的时间内运行大约 10k 行

select MachineName,count(Message) from Telemetry where TimeStamp between DATEADD(HOUR,-24, getutcdate()) and getutcdate() group by MachineName

但是,当我尝试使硬编码的 -24 可配置并添加一个变量时,执行查询需要超过 5 分钟。

DECLARE @cutoff int; SET @cutoff = 24

select MachineName,count(Message) from Telemetry where TimeStamp between DATEADD(HOUR, -1*@cutoff, getutcdate()) and getutcdate() group by MachineName

性能显着下降有什么具体原因吗?在不影响性能的情况下添加变量的最佳方法是什么?

【问题讨论】:

【参考方案1】:

我的猜测是您在 MachineName 上也有一个索引 - 或者 SQL 正在决定,因为它需要按 MachineName 分组,所以这将是访问记录的更好方法。

按照 AngularRat 的建议更新统计数据是一个好的开始 - 但 SQL 通常会自动维护这些数据。 (事实上​​,当SQL提前知道24小时间隔时的良好性能是统计良好的证据......但是当SQL不提前知道BETWEEN的大小时,那么它认为其他方法可能是更好的主意)。

给定:

CREATE TABLE Telemetry  ( machineName sysname, message varchar(88), [timestamp] timestamp)
CREATE INDEX Telemetry_TS ON Telemetry([timestamp]);

首先,尝试OPTION (OPTIMIZE FOR ( @cutoff = 24 )); 子句让SQL 知道如何处理查询,如果这还不够,请尝试WITH (Index( Telemetry_TS))。使用 INDEX 提示不太理想。

DECLARE @cutoff int = 24;
select MachineName,count(Message) 
from Telemetry  -- WITH (Index( Telemetry_TS))
where TimeStamp between DATEADD(HOUR, -1*@cutoff, getutcdate()) and getutcdate() 
group by MachineName
OPTION (OPTIMIZE FOR ( @cutoff = 24 )); 

【讨论】:

是的,MachineName 上还有另一个索引。我尝试添加 OPTION (OPTIMIZE FOR (@cutoff = 24)) 子句,效果很好!我猜 SQL server 选择了错误的执行计划,而没有使用 option 子句指定值。 不是错误计划,只是不是您希望的计划。 SQL 有优化规则,它适用于猜测每个查询谓词的“选择性”...有多少行将“命中”BETWEEN -vs- 和 EQUAL -vs- GREATER THAN (>)。对于未知值,SQL 假定 MANY ROWS 将匹配 BETWEEN - 提示为其提供了高级知识。编号blogs.msdn.com/b/bartd/archive/2011/01/25/… 同意。 “错误”可能不是在这里描述它的最佳方式。 option 子句提示我只寻找非常有限的数据范围,这就是我希望使用查询的方式。【参考方案2】:

您的参数实际上应该可以工作,但您可能会看到一个问题,即数据库使用过时的统计信息进行查询计划。我会尝试更新您正在查询的表的统计信息。比如:

UPDATE STATISTICS TableName;

此外,如果您的代码在存储过程中运行,您可能需要重新编译该过程。比如:

EXEC sp_recompile N'ProcedureName';

很多时候,当我有一个查询似乎应该运行得更快但实际上并非如此,这是一个统计/查询计划过时的问题。

参考资料:

https://msdn.microsoft.com/en-us/library/ms187348.aspx

https://msdn.microsoft.com/en-us/library/ms190439.aspx

【讨论】:

感谢您的回复。现在手动执行查询,而不是在存储过程中执行。我尝试了 UPDATE STATISTICS,似乎并没有提高性能。

以上是关于带有时间戳和变量的 SQL Server 查询性能的主要内容,如果未能解决你的问题,请参考以下文章

Sql Server 查询性能

SQL Server 索引性能受变量影响

带有未声明前缀的 SQL Server Xml 查询

如何在 SQL Server 中列出所有带有“WITH NOCHECK”的外键

提高 SQL Server 查询性能

大型sql server查询性能优化