我需要测量几个查询的持续时间,如下所示:
declare @dtStart1 as datetime;
declare @dtStart2 as datetime;
declare @dtStart3 as datetime;
declare @dtStart4 as datetime;
declare @dtStart5 as datetime;
declare @dtStart6 as datetime;
declare @dtStart7 as datetime;
declare @dtStart8 as datetime;
declare @dtStart9 as datetime;
declare @dtStart10 as datetime;
declare @duration1 as int;
declare @duration2 as int;
declare @duration3 as int;
declare @duration4 as int;
declare @duration5 as int;
declare @duration6 as int;
declare @duration7 as int;
declare @duration8 as int;
declare @duration9 as int;
declare @duration10 as int;
set @dtStart1 = (select getutcdate());
--query1
set @duration1 = (select datediff(millisecond, @dtStart1, GETUTCDATE()));
set @dtStart2 = (select getutcdate());
--query2
set @duration2 = (select datediff(millisecond, @dtStart2, GETUTCDATE()));
set @dtStart3 = (select getutcdate());
--query3
set @duration3 = (select datediff(millisecond, @dtStart3, GETUTCDATE()));
set @dtStart4 = (select getutcdate());
--query4
set @duration4 = (select datediff(millisecond, @dtStart4, GETUTCDATE()));
set @dtStart5 = (select getutcdate());
--query5
set @duration5 = (select datediff(millisecond, @dtStart5, GETUTCDATE()));
set @dtStart6 = (select getutcdate());
--query6
set @duration6 = (select datediff(millisecond, @dtStart6, GETUTCDATE()));
set @dtStart7 = (select getutcdate());
--query7
set @duration7 = (select datediff(millisecond, @dtStart7, GETUTCDATE()));
set @dtStart8 = (select getutcdate());
--query8
set @duration8 = (select datediff(millisecond, @dtStart8, GETUTCDATE()));
set @dtStart9 = (select getutcdate());
--query9
set @duration9 = (select datediff(millisecond, @dtStart9, GETUTCDATE()));
set @dtStart10 = (select getutcdate());
--query10
set @duration10 = (select datediff(millisecond, @dtStart10, GETUTCDATE()));
select @duration1 / 1000.0 as q1,
@duration2 / 1000.0 as q2,
@duration3 / 1000.0 as q3,
@duration4 / 1000.0 as q4,
@duration5 / 1000.0 as q5,
@duration6 / 1000.0 as q6,
@duration7 / 1000.0 as q7,
@duration8 / 1000.0 as q8,
@duration9 / 1000.0 as q9,
@duration10 / 1000.0 as q10;
问题是除了我真正感兴趣的结果之外,我还得到了查询的结果。我尝试为每个查询使用cursor
,但即使是长时间查询也是如此。可能它只是定义但未执行。我已尝试将FMTONLY
设置为ON
,然后设置为OFF
,但这对于长查询也是即时的,甚至在结果中显示了列名称。我想实现执行查询,获取持续时间就像查询通常是unning的情况一样,但不会将其返回给我的应用程序服务器,在那里处理查询可能返回的数百万条记录会有问题,而不是提到内存的巨大浪费与获得我感兴趣的一行的理想结果相比,即结果。
答案 0 :(得分:3)
很少有选择。
抑制查询结果集的一种明显方法是将查询结果插入到#temp表中,然后删除临时表。这会影响查询运行时间,但相对容易实现。只需在查询INTO #temp
之后添加SELECT
子句即可。调用应用程序不需要更改。
更改调用应用程序并使其期望这些结果集。测量"第一行时间"一旦应用程序收到第一行就停止查询。实施这将是一项相当重要的任务。
更改查询,以使其结果存储在变量中,而不是临时表中。每列一个变量。
注意:在评论中指出Martin Smith,将列值分配到变量中可能会改变计划的形状,如answer中所示: sql execution latency when assign to a variable,所以你应该谨慎使用选项3。
例如,如果您有查询
SELECT
Col1
,Col2
,Col3
FROM YourTable
... some complex logic
;
将其更改为以下内容:
DECLARE @VarCol1 bigint;
DECLARE @VarCol2 int;
DECLARE @VarCol3 datetime2(0);
-- use appropriate types that match the query columns
SELECT
@VarCol1 = Col1
,@VarCol2 = Col2
,@VarCol3 = Col3
FROM YourTable
... some complex logic
;
这样的查询将完全运行(而不是在SELECT COUNT(*)
中包装查询),但其结果将存储在局部变量中。每个新行都将覆盖变量值,但它应该比使用#temp table更少开销。
您可以通过添加
轻松验证和比较方法1和3SET STATISTICS TIME ON;
SET STATISTICS IO ON;
在查询和
之前SET STATISTICS TIME OFF;
SET STATISTICS IO OFF;
查询后。
尝试运行原始查询,查询并将结果保存到#temp表中,查询并将结果保存到变量中并比较CPU和读数。
在我的测试中,对于将结果保存到变量中的正常查询和查询,读取次数相同。 elapsed time
中包含变量的查询要快得多,但有CPU time
,因为没有网络流量。
将结果保存到临时表中的查询具有更多读取,并且比将结果保存到变量的查询稍慢。
我有一个大表,我的测试查询只是从中读取1M行:
SELECT
TOP (1000000)
[ID]
,[ElevatorID]
,[TimestampUTC]
FROM [dbo].[ArchivePlaybackStatsDay];
DECLARE @VarID bigint;
DECLARE @VarElevatorID int;
DECLARE @VarTimestampUTC int;
SELECT
TOP (1000000)
@VarID = [ID]
,@VarElevatorID = [ElevatorID]
,@VarTimestampUTC = [TimestampUTC]
FROM [dbo].[ArchivePlaybackStatsDay];
SELECT
TOP (1000000)
[ID]
,[ElevatorID]
,[TimestampUTC]
INTO #Temp
FROM [dbo].[ArchivePlaybackStatsDay];
DROP TABLE #Temp;
我在SQL Sentry Plan Explorer中运行它并得到了这些统计信息:
您可以看到第一行和第二行的读取相同,CPU已关闭,但持续时间非常不同,因为第一个查询实际上将1M行传输到客户端。与使用变量的第二个查询相比,使用#temp表的第三个查询有一些额外的开销。
我添加了另一个变体,它将所有列转换为varbinary
变量以统一变量声明。不幸的是,转换为varbinary
,特别是varbinary(max)
会产生明显的开销。
DECLARE @VarBin varbinary(8000);
SELECT
TOP (1000000)
@VarBin = [ID]
,@VarBin = [ElevatorID]
,@VarBin = [TimestampUTC]
FROM [dbo].[ArchivePlaybackStatsDay];
DECLARE @VarBinMax varbinary(max);
SELECT
TOP (1000000)
@VarBinMax = [ID]
,@VarBinMax = [ElevatorID]
,@VarBinMax = [TimestampUTC]
FROM [dbo].[ArchivePlaybackStatsDay];
答案 1 :(得分:1)
您可以尝试通过
获得非常近似的衡量标准declare @dummyCounter as int;
set @dummyCounter = (Select count(*)
from (
/* original query */
) t);
最终它可能与原始计划有不同的计划