Rad*_*hiu 3 sql-server sql-server-2008-r2
我有一个在使用时正在运行的存储过程,SET STATISTICS TIME ON
该过程的总体执行时间为 31 秒,但是在查看来自 的信息时STATISTICS TIME
,将每个查询的所有经过时间相加的结果大于 31秒。
例如:
SQL Server Execution Times: CPU time = 109 ms, elapsed time = 128 ms.
SQL Server Execution Times: CPU time = 156 ms, elapsed time = 159 ms.
SQL Server Execution Times: CPU time = 1528 ms, elapsed time = 15901 ms.
SQL Server Execution Times: CPU time = 1248 ms, elapsed time = 8055 ms.
SQL Server Execution Times: CPU time = 6037 ms, elapsed time = 30433 ms.
SQL Server Execution Times: CPU time = 6069 ms, elapsed time = 30776 ms.
SQL Server Execution Times: CPU time = 0 ms, elapsed time = 0 ms.
Run Code Online (Sandbox Code Playgroud)
我觉得我在尝试阅读这里的信息时把事情搞混了,因为查询的执行时间肯定不是 85452 毫秒。
另外,我知道如果 CPU 时间大于经过的时间,那么查询会并行执行,即使在实际执行计划中仔细检查,也不会执行任何并行操作。
那么,为什么经过的时间STATISTICS TIME
与查询的实际执行时间不同呢?
这些SET STATISTICS
选项将报告每个语句的统计信息,当与过程结合使用时,可以导致包括有效的“摘要”结果 - 随着对过程本身的调用解析,将返回一个额外的统计记录,其中包含过程本身的统计信息.
如果一个过程执行诸如调用另一个过程之类的操作,这可能会导致多个“摘要”结果。
为了说明SET STATISTICS
选项何时返回信息,我们可以创建几个过程,其中一个只是调用另一个。
USE tempdb;
GO
IF ( OBJECT_ID( 'dbo.TestProc', 'P' ) IS NULL )
BEGIN
EXEC( 'CREATE PROCEDURE dbo.TestProc AS SET NOCOUNT ON;' );
END;
GO
ALTER PROCEDURE dbo.TestProc
AS BEGIN
-- SET NOCOUNT ON; -- Excluded to reduce noise for the example;
SELECT TOP 100000 sao1.*
INTO #t_Test
FROM sys.all_objects sao1
CROSS APPLY sys.all_objects sao2;
SELECT TOP 100000 *
INTO #t_Test2
FROM sys.all_objects sao1;
DROP TABLE #t_Test;
DROP TABLE #t_Test2;
END;
GO
IF ( OBJECT_ID( 'dbo.TestSuperProc', 'P' ) IS NULL )
BEGIN
EXEC( 'CREATE PROCEDURE dbo.TestSuperProc AS SET NOCOUNT ON;' );
END;
GO
ALTER PROCEDURE dbo.TestSuperProc
AS BEGIN
-- SET NOCOUNT ON; -- Excluded to reduce noise for the example;
EXECUTE dbo.TestProc;
END;
GO
Run Code Online (Sandbox Code Playgroud)
准备好这些过程后,让我们打开STATISTICS TIME
并运行通过执行任一过程而执行的操作,而无需实际调用:
-- Just procedure contents;
SET NOCOUNT ON;
SET STATISTICS TIME ON;
SELECT TOP 100000 sao1.*
INTO #t_Test
FROM sys.all_objects sao1
CROSS APPLY sys.all_objects sao2;
SELECT TOP 100000 *
INTO #t_Test2
FROM sys.all_objects sao1;
DROP TABLE #t_Test;
DROP TABLE #t_Test2;
SET NOCOUNT OFF;
SET STATISTICS TIME OFF;
Run Code Online (Sandbox Code Playgroud)
输出看起来有点像这样:
SQL Server 执行时间: CPU 时间 = 171 毫秒,已用时间 = 305 毫秒。 SQL Server 执行时间: CPU 时间 = 47 毫秒,经过时间 = 40 毫秒。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 2 毫秒。 SQL Server 执行时间: CPU 时间 = 0 ms,经过时间 = 8 ms。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 0 毫秒。
匹配这一切看起来正如预期的那样:
SET NOCOUNT ON;
SET STATISTICS TIME ON;
-- Statistics will now start being reported;
SELECT TOP 100000 sao1.*
INTO #t_Test
FROM sys.all_objects sao1
CROSS APPLY sys.all_objects sao2;
Run Code Online (Sandbox Code Playgroud)
SQL Server 执行时间:CPU 时间 = 171 毫秒,已用时间 = 305 毫秒。
SELECT TOP 100000 *
INTO #t_Test2
FROM sys.all_objects sao1;
Run Code Online (Sandbox Code Playgroud)
SQL Server 执行时间:CPU 时间 = 47 毫秒,已用时间 = 40 毫秒。
DROP TABLE #t_Test;
Run Code Online (Sandbox Code Playgroud)
SQL Server 执行时间:CPU 时间 = 0 毫秒,已用时间 = 2 毫秒。
DROP TABLE #t_Test2;
Run Code Online (Sandbox Code Playgroud)
SQL Server 执行时间:CPU 时间 = 0 毫秒,已用时间 = 8 毫秒。
SET NOCOUNT OFF;
Run Code Online (Sandbox Code Playgroud)
SQL Server 执行时间:CPU 时间 = 0 毫秒,已用时间 = 0 毫秒。
-- Statistics will now stop being reported;
SET STATISTICS TIME OFF;
Run Code Online (Sandbox Code Playgroud)
四个语句 ( SELECT
, SELECT
, DROP
, DROP
) 加上SET NOCOUNT OFF;
第五个语句的 a,来自STATISTICS TIME
.
但是,如果我们要通过运行该过程来捕获统计信息:
-- Procedure statistics;
SET NOCOUNT ON;
SET STATISTICS TIME ON;
EXECUTE dbo.TestProc;
SET NOCOUNT OFF;
SET STATISTICS TIME OFF;
Run Code Online (Sandbox Code Playgroud)
SQL Server 执行时间: CPU 时间 = 140 毫秒,已用时间 = 488 毫秒。 SQL Server 执行时间: CPU 时间 = 47 毫秒,经过时间 = 40 毫秒。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 1 毫秒。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 0 毫秒。 SQL Server 执行时间: CPU 时间 = 187 毫秒,已用时间 = 529 毫秒。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 0 毫秒。
突然,返回了第六条消息——这是一条指示过程本身的总统计信息的消息,并且是过程中包含的语句的总和。我们可以STATISTICS TIME
通过执行dbo.TestSuperProc
我们创建的结果在结果中生成第七条摘要记录:
-- Super Proc statistics;
SET NOCOUNT ON;
SET STATISTICS TIME ON;
EXECUTE dbo.TestSuperProc;
SET NOCOUNT OFF;
SET STATISTICS TIME OFF;
Run Code Online (Sandbox Code Playgroud)
SQL Server 执行时间: CPU 时间 = 187 毫秒,已用时间 = 259 毫秒。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 42 毫秒。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 4 毫秒。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 0 毫秒。 SQL Server 执行时间: CPU 时间 = 187 毫秒,已用时间 = 307 毫秒。 SQL Server 执行时间: CPU 时间 = 187 毫秒,已用时间 = 307 毫秒。 SQL Server 执行时间: CPU 时间 = 0 毫秒,经过时间 = 0 毫秒。
实际上,您的倒数第二条消息(可能SET NOCOUNT OFF
在我的示例中的a 之前)报告了您期望的 31 秒 - 总 CPU 和调用过程所用的时间。正如您似乎知道的,CPU 时间确实是您要注意性能调优的地方,因为如果查询并行,它可能会高于经过的时间,或者如果过程花费时间在等待信号和 I/ O 操作。