带有时间戳和变量的 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 查询性能的主要内容,如果未能解决你的问题,请参考以下文章