我有一个简单的SQL查询来计算过去24小时内客户的遥测记录数。
使用TimeStamp上的索引,对于大约10k行,以下查询在不到1秒的时间内运行
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
性能显着下降是否有任何具体原因?在不影响性能的情况下添加变量的最佳方法是什么?
答案 0 :(得分: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 ));
答案 1 :(得分:0)
您的参数应该可以正常工作,但您可能会看到数据库使用查询计划的过期统计信息的问题。我会尝试更新您正在查询的表的统计信息。类似的东西:
UPDATE STATISTICS TableName;
此外,如果您的代码是在存储过程中运行的,则可能需要重新编译该过程。类似的东西:
EXEC sp_recompile N'ProcedureName';
很多时候,如果我的查询看起来应该运行得快得多,但事实并非如此,这是一个过时的统计/查询计划问题。
参考文献: