【发布时间】:2012-04-25 22:16:08
【问题描述】:
我有一个存储过程,我使用公用表表达式在菜单上构建分层路径(因此它可以显示类似父菜单 -> 子菜单 -> 子子菜单 -> ...)
它非常适合我想用它来做的事情,当我将从递归 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 相对较慢,可能涉及多个表扫描。除非您提供有关 CTE 所涉及的表的更多详细信息以及这些表中的大致行数,否则我认为不可能回答您的问题
-
@a1ex07 你通常不能这么说。非递归 CTE 等效于视图。它在查询编译期间完全消失。在递归的情况下,它完全取决于你在做什么。
-
如果您发布 where 子句或其余的连接,它可能更有意义。在我看来,你在 CTE 中所做的一切都很正常。
标签: sql sql-server performance common-table-expression