Sql server 是什么导致DMV显示空查询计划?
当我执行这个简单的SP,然后从后面的DMV查询中检查查询计划时,查询计划返回为NULL。但如果我注释掉SP中的else块(或将其更改为not reference temp table),DMV查询将显示一个查询计划。知道是什么导致了这种差异吗?空查询计划是否意味着未缓存任何内容?我正在使用SQLServer2008R2Sql server 是什么导致DMV显示空查询计划?,sql-server,sql-server-2008-r2,Sql Server,Sql Server 2008 R2,当我执行这个简单的SP,然后从后面的DMV查询中检查查询计划时,查询计划返回为NULL。但如果我注释掉SP中的else块(或将其更改为not reference temp table),DMV查询将显示一个查询计划。知道是什么导致了这种差异吗?空查询计划是否意味着未缓存任何内容?我正在使用SQLServer2008R2 CREATE PROCEDURE dbo.SampleSp ( @Option TINYINT ) AS DECLARE @RowCount INT;
CREATE PROCEDURE dbo.SampleSp
(
@Option TINYINT
)
AS
DECLARE @RowCount INT;
-- Get ID into local temp table
CREATE TABLE #P (ID INT PRIMARY KEY);
INSERT INTO #P
VALUES (1), (2)
IF @Option = 1
BEGIN
SELECT ID FROM #P
END
ELSE
BEGIN
SELECT ID FROM #P
END
GO
--Call SP
EXEC dbo.SampleSp 1
GO
--DMV Query to find query_plan
SELECT
CP.objtype,
CP.usecounts AS Ct,
ST.last_execution_time,
SUBSTRING(Text, (statement_start_offset / 2) + 1, (CASE statement_end_offset WHEN -1 THEN DATALENGTH(Text) ELSE statement_end_offset END - ((statement_start_offset / 2) + 1))) AS query,
T.text,
PL.query_plan
FROM sys.dm_exec_cached_plans AS CP WITH(NOLOCK)
CROSS APPLY sys.dm_exec_sql_text(CP.plan_handle) AS T
OUTER APPLY sys.dm_exec_query_plan(CP.plan_handle) AS PL
LEFT OUTER JOIN sys.dm_exec_query_stats AS ST WITH(NOLOCK) ON ST.plan_handle = CP.plan_handle
WHERE 1=1
AND ST.last_execution_time > DATEADD(MINUTE, -5, GETDATE())
AND T.text LIKE '%SampleSp%'
AND T.text NOT LIKE '%dm_exec_cached_plans%'
ORDER BY ST.last_execution_time DESC
我想我知道了。在执行SP中的每个分支之前,计划似乎都将显示为NULL。(您可以通过使用参数值2再次调用SP来看到这一点,然后该计划就会出现。)如果只执行了SP的一部分,SQL Server会在内部执行缓存而不是计划(您可以通过查看usecounts以及我为证明这一点而做的一些其他更广泛的测试来看到这一点),但它不会出现在我使用的DMV查询中。这就提出了一个问题:您如何查看已缓存的SP部分的计划?请使用DATEADD(MINUTE,-5,GETDATE())-日期/时间的隐式数学对新的数据类型不起作用,在某个时候,这些DMV可能会切换到更高的精度,您的所有查询都会中断。不过,回到问题上来,您是否启用了针对特殊工作负载的
优化设置?可能没有返回任何查询计划,因为您只运行了一次查询,并且只存储了一个存根。没有,未启用“针对临时工作负载优化”设置。您是否完全确定,如果使用相同的参数再次调用该计划,该计划将不会显示?是的,我测试了它。你自己试试看。在执行所有分支的那一刻,它显示了计划。我在SQL 2012中得到了相同的结果(没有查询计划)。实际的查询要复杂得多:一些设置代码,一个用于填充工作临时表的四向分支,然后是一个用于返回两个结果集之一的双向分支。我确认我必须让它在四个分支中的每一个,以及每一个末端分支中出现。但是:当我将proc更改为临时表(@temp)而不是tempdb(#temp)表时,整个问题就消失了——然后计划总是显示出来。(撇开我想要@temp还是#temp的问题不谈。)