Sql server DMV上的递归公共表表达式是否应该构建在缓存数据上?
我已经编写了一个小CTE来获取头部拦截器进程的总阻塞时间,我不确定是否应该首先将我希望CTE运行的所有进程复制到一个临时表中,然后在此表上执行查询-即,我希望确保在查询运行和(最坏情况下)时,数据不能在我脚下更改,我最终得到了一个无限递归循环 这是我的SQL,包括temp表-出于性能原因,我不想使用该表,而是直接转到CTE中的sysprocesss dmv,但我不确定这可能带来的影响Sql server DMV上的递归公共表表达式是否应该构建在缓存数据上?,sql-server,tsql,common-table-expression,dynamic-management-views,Sql Server,Tsql,Common Table Expression,Dynamic Management Views,我已经编写了一个小CTE来获取头部拦截器进程的总阻塞时间,我不确定是否应该首先将我希望CTE运行的所有进程复制到一个临时表中,然后在此表上执行查询-即,我希望确保在查询运行和(最坏情况下)时,数据不能在我脚下更改,我最终得到了一个无限递归循环 这是我的SQL,包括temp表-出于性能原因,我不想使用该表,而是直接转到CTE中的sysprocesss dmv,但我不确定这可能带来的影响 DECLARE @proc TABLE( spid SMALLINT PRIMARY KEY,
DECLARE @proc TABLE(
spid SMALLINT PRIMARY KEY,
blocked SMALLINT INDEX blocked_index,
waittime BIGINT)
INSERT INTO @proc
SELECT spid, blocked, waittime
FROM master..sysprocesses
;WITH block_cte AS
(
SELECT spid, CAST(blocked AS BIGINT) [wait_time], spid [root_spid]
FROM @proc
WHERE blocked = 0
UNION ALL
SELECT blocked.spid, blocked.waittime, block_cte.spid
FROM @proc AS blocked
INNER JOIN block_cte ON blocked.blocked = block_cte.spid
)
SELECT root_spid blocking_spid, SUM(wait_time) total_blocking_time
FROM block_cte
GROUP BY root_spid
这个问题最好转移到堆栈DBA。我相信那些聪明的人不仅能告诉你答案,还能告诉你背后的原因 我自己也不确定,我决定测试一下 我的脚本捕获了1000次的记录计数。现在要做到这一点,我必须绕过CTE的几个限制。在…之间你不能使用。这使得计算记录相当困难。因此,我创建了一个内联表函数来从sysprocesss返回当前行数 系统进程计数功能
CREATE FUNCTION ProcessCount()
RETURNS TABLE
AS
RETURN
(
-- Return the current process count.
SELECT
COUNT(*) AS RecordCount
FROM
Master..sysProcesses
)
;
我把这个函数包装在一个CTE中
CTE
WITH RCTE AS
(
/* CTE to test if recursion is effected by updates to
* underlying data.
*/
-- Anchor part.
SELECT
1 AS ExecutionCount,
1 AS JoinField,
RecordCount
FROM
ProcessCount()
UNION ALL
-- Recursive part.
SELECT
r.ExecutionCount + 1 AS ExecutionCount,
1 AS JoinField,
pc.RecordCount
FROM
ProcessCount() AS pc
INNER JOIN RCTE AS r ON r.JoinField = 1
WHERE
r.ExecutionCount < 1000
)
SELECT
MIN(RecordCount) AS MinRecordCount,
MAX(RecordCount) AS MaxRecordCount
FROM
RCTE
OPTION
(MAXRECURSION 1000)
;
GO
当然,内联函数可能是罪魁祸首。它确实改变了我的执行计划。这给了我一个教训。我真的需要更好地理解执行计划。我相信阅读老年退休金计划会提供一个明确的答案 除非将MAXRECURSION选项设置为0,否则无需担心无限循环。默认递归限制为100。现在我不是100%确定,但我希望它能保护您免受流沙的影响。是的,我不会将MAXRECURSION设置为0:)-但我可能会将其设置为100以上。很高兴知道CTE对DMV的“推荐做法”是什么-我感觉这基本上相当于在DMV上运行一组长的重复查询,而且,由于DMV中的D,如果我想保证一致性,我应该复制到临时表中。谢谢-DBA交换的优点-我已经忘记了这一点。是的,所以你的发现确实指向了整个CTE执行过程中的观点变化——感谢你巩固了这一点!我想我现在还是用我的表变量吧
Run Min Max
1 113 254
2 107 108
3 86 108