Sql 加入CTE性能
我有一个存储过程,在这个过程中,我使用一个公共表表达式在菜单上构建一个分层路径(这样它可以显示类似于父菜单->子菜单->子子菜单->…) 它对于我想要使用它的目的非常有效,问题是当我将从递归CTE获得的信息放入我真正想要的信息中时。我从我的数据到CTE做一个内部连接,并得到分层路径。对于返回约300行的内容,存储过程平均需要15-20秒 当我将CTE的结果插入临时表并基于该表进行连接时,该过程只需不到一秒钟的时间 我只是想知道为什么只使用CTE需要这么长时间,或者我是否在某种程度上滥用了CTE **编辑这本质上是存储过程Sql 加入CTE性能,sql,sql-server,performance,common-table-expression,Sql,Sql Server,Performance,Common Table Expression,我有一个存储过程,在这个过程中,我使用一个公共表表达式在菜单上构建一个分层路径(这样它可以显示类似于父菜单->子菜单->子子菜单->…) 它对于我想要使用它的目的非常有效,问题是当我将从递归CTE获得的信息放入我真正想要的信息中时。我从我的数据到CTE做一个内部连接,并得到分层路径。对于返回约300行的内容,存储过程平均需要15-20秒 当我将CTE的结果插入临时表并基于该表进行连接时,该过程只需不到一秒钟的时间 我只是想知道为什么只使用CTE需要这么长时间,或者我是否在某种程度上滥用了CTE
With Hierarchical_Path (Menu_ID, Parent_ID, Path)
As
(
Select
EM.Menu_Id, Parent_ID,
Convert(varchar(max),
EM.Description) as Path
From
Menu EM
Where
--EM.Topic_No is null
EM.Parent_ID = 0 and EM.Disabled = 0
Union All
Select
EM.Menu_ID,
EM.Parent_ID,
Convert(Varchar(max),E.Path + ' -> ' + EM.Description) as Path
From
Menu EM
Inner Join
Hierarchical_Path E
On
EM.Parent_ID = E.Menu_ID
)
SELECT distinct
EM.Description
,EMS.Path
FROM
dbo.Menu em
INNER JOIN
Hierarchical_Path EMS
ON
EMS.Menu_ID = em.Menu_Id
2 more INNER JOINs
2 Left Joins
WHERE Clause
当我像这样运行查询(加入CTE)时,性能大约为20秒
当我将CTE结果插入一个临时表,并加入其中时,性能是瞬间的
再把我的查询分解一下,它似乎就挂在where子句上了。我想我的问题更多的是,CTE到底什么时候运行,它是否存储在内存中?我运行时的假设是,它被调用一次,然后留在内存中,但在某些情况下,它可以被调用多次吗?区别在于CTE不会持久化,而临时表(至少对于会话而言)会持久化。连接到非持久性列意味着与临时表中已预计算的同一列相比,SQL对数据没有任何统计信息。基本上,临时表缓存了您将要使用的内容,SQL Server可以更好地对此进行优化。当连接函数或表变量的结果时,也会遇到同样的问题 我猜您的CTE执行计划是使用单个线程执行,而临时表可以使用多个线程。您可以在运行查询时包括实际执行计划,并在每个运算符上查找指向相反方向的两个水平箭头,从而检查这一点。这表明了并行性
注意-尝试设置“set statistics io on”和“set statistics time on”,以查看无论运行持续时间如何,运行查询的实际成本是否相同。请在此处显示可比较的查询。递归CTE相对较慢,可能涉及多个表扫描。除非您提供有关CTE中所涉及的表的更多详细信息以及这些表中的大致行数,否则我相信无法回答您的问题question@a1ex07你根本不能这么说。非递归CTE相当于视图。它在查询编译期间完全消失。在递归情况下,它完全取决于您正在做什么。如果您发布where子句或其他连接,它可能更有意义。你在CTE里做的一切对我来说都很正常。