SQL 带有时间戳和变量的服务器查询性能
SQL Server Query Performance with Timestamp and variable
我有一个简单的 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
性能明显下降有什么具体原因吗?在不影响性能的情况下添加变量的最佳方法是什么?
您的参数实际上应该有效,但您可能会看到数据库使用查询计划的过时统计信息的问题。我会尝试更新您正在查询的 table 的统计信息。类似于:
UPDATE STATISTICS TableName;
此外,如果您的代码 运行ning 来自存储过程,您可能需要重新编译该过程。类似于:
EXEC sp_recompile N'ProcedureName';
很多时候我的查询看起来应该 运行 快很多但实际上不是,这是一个 statistic/query 计划过时的问题。
参考文献:
我的猜测是您在 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 ));
我有一个简单的 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
性能明显下降有什么具体原因吗?在不影响性能的情况下添加变量的最佳方法是什么?
您的参数实际上应该有效,但您可能会看到数据库使用查询计划的过时统计信息的问题。我会尝试更新您正在查询的 table 的统计信息。类似于:
UPDATE STATISTICS TableName;
此外,如果您的代码 运行ning 来自存储过程,您可能需要重新编译该过程。类似于:
EXEC sp_recompile N'ProcedureName';
很多时候我的查询看起来应该 运行 快很多但实际上不是,这是一个 statistic/query 计划过时的问题。
参考文献:
我的猜测是您在 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 ));