你可以接近你在性能监视器和活动监视器看到SQL Compilations/sec
和Batch Requests/sec
,在运行在单独的查询窗口,部分批次的测试,具体如下。
查询窗口1:
DECLARE @t1 datetime;
DECLARE @t2 datetime;
DECLARE @CompVal1 int;
DECLARE @CompVal2 int;
DECLARE @ReCompVal1 int;
DECLARE @ReCompVal2 int;
DECLARE @BatchVal1 int;
DECLARE @BatchVal2 int;
DECLARE @ElapsedMS decimal(10,2);
SELECT @t1 = GETDATE()
, @CompVal1 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'SQL Compilations/sec '
)
, @ReCompVal1 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'SQL Re-Compilations/sec '
)
, @BatchVal1 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'Batch Requests/sec '
);
WAITFOR DELAY '00:00:10.000';
SELECT @t2 = GETDATE()
, @CompVal2 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'SQL Compilations/sec '
)
, @ReCompVal2 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'SQL Re-Compilations/sec '
)
, @BatchVal2 = (
SELECT spi.cntr_value
FROM sys.sysperfinfo spi
WHERE spi.counter_name = 'Batch Requests/sec '
);
SET @ElapsedMS = DATEDIFF(MILLISECOND, @t1, @t2);
SELECT ElapsedTimeMS = @ElapsedMS
, [SQL Compilations/sec] = (@CompVal2 - @CompVal1) / @ElapsedMS * 1000
, [SQL Recompilations/sec] = (@ReCompVal2 - @ReCompVal1) / @ElapsedMS * 1000
, [Batch Requests/sec] = (@BatchVal2 - @BatchVal1) / @ElapsedMS * 1000;
在上面的代码运行时,在查询窗口2中,运行以下命令。该代码仅执行100个T-SQL批处理:
EXEC sys.sp_executesql N'SELECT TOP(1) o.name FROM sys.objects o;';
GO 100
如果切换回查询窗口1,您将看到类似以下内容:
╔═══════════════╦══════════════════════╦══════════ ══════════════╦════════════════════╗
lapse ElapsedTimeMS║SQL编译/秒║SQL重新编译/秒║批处理请求/秒║
╠═══════════════╬══════════════════════╬══════════ ══════════════╬════════════════════╣
║10020.00║10.07984031000║0.00000000000║10.07984031000║
╚═══════════════牛皮══════════════════════牛皮══════════ ══════════════牛皮════════════════════╝
如果我们看这个查询:
SELECT dest.text
, deqs.execution_count
FROM sys.dm_exec_query_stats deqs
CROSS APPLY sys.dm_exec_sql_text(deqs.plan_handle) dest
WHERE dest.text LIKE 'SELECT TOP(1)%'
我们可以确认测试查询有100次执行。
在上面的结果,你可以看到我们正在编译每一次的sp_executesql
语句执行。当然,该计划已被缓存,但是我们看到了它的编译结果。是什么赋予了?
在微软的文档说,这一下sp_executesql
:
对于批处理,名称范围和数据库上下文,sp_executesql具有与EXECUTE相同的行为。在执行sp_executesql语句之前,不会编译sp_executesql @stmt参数中的Transact-SQL语句或批处理。然后,将@stmt的内容编译并作为一个执行计划,与名为sp_executesql的批处理的执行计划分开执行。
因此,即使命令高速缓存中已经存在命令文本的计划,sp_executesql
它也会在每次运行时进行编译。@PaulWhite在他的回答中表明,实际上对sp_executesql的大多数调用都没有缓存。