[英]Why this CTE expression hangs while temp table runs fine
我在下面的SQL CTE语句中发现了性能瓶颈。 在调试时,它只是挂在那儿(我认为它可以进行表扫描),所以我用临时表替换了它,查询运行良好。 我想知道在使语句挂起的CTE表达式的编写方式上是否存在某些差异。 我知道CTE会对性能造成一定的影响,但是我不认为我在下面的查询中做了任何特别的事情,以使CTE表现不佳。
;with ContList (ContKey, CKey, CreatedDate, DeletedDate, SourceId) AS
(
SELECT ContKey, CKey, CreatedDate, DeletedDate, SourceId FROM #someTempTable
UNION ALL
SELECT list.ContKey AS ContKey,
fact.CKey AS CKey,
case when fact.CreatedDate > list.CreatedDate then fact.CreatedDate else list.CreatedDate end AS CreatedDate,
case when isnull(fact.DeletedDate, '9999/01/01') < isnull(list.DeletedDate, '9999/01/01') then fact.DeletedDate else list.DeletedDate end AS DeletedDate,
fact.DataSourceDimKey As SourceId
FROM ContList list
INNER JOIN SomeFact fact ON list.CKey = fact.DimKey
INNER JOIN SomeDimvw someDim on someDim.SomeKey = fact.SomeKey
INNER JOIN #contTypes contTypes on someDim.SomeTypeId = contTypes.SomeTypeId
WHERE list.DeletedDate IS NULL
)
我将上面的查询替换为:
SELECT ContKey, CKey, CreatedDate, DeletedDate, SourceId FROM #someTempTable
UNION ALL
SELECT list.ContKey AS ContKey,
fact.CKey AS CKey,
case when fact.CreatedDate > list.CreatedDate then fact.CreatedDate else list.CreatedDate end AS CreatedDate,
case when isnull(fact.DeletedDate, '9999/01/01') < isnull(list.DeletedDate, '9999/01/01') then fact.DeletedDate else list.DeletedDate end AS DeletedDate,
fact.DataSourceDimKey As SourceId
into #ContList
FROM #ContList list
INNER JOIN SomeFact fact ON list.CKey = fact.DimKey
INNER JOIN SomeDimvw someDim on someDim.SomeKey = fact.SomeKey
INNER JOIN #contTypes contTypes on someDim.SomeTypeId = contTypes.SomeTypeId
WHERE list.DeletedDate IS NULL
)
最近,我遇到了一个(可能是相关的)情况,即使用CTE进行复杂的查询会产生不一致的结果,具体取决于提供的参数。
例如:
第一次测试:
第二次测试:
原来,为“ A”生成的查询计划是有效的,而为“ B”生成的查询计划则没有效率。 由于查询计划已缓存,因此第一个查询在服务器重新启动后运行,这将控制所有查询的性能。
解决方案是强制重建数据库的统计信息。
CTE只是语法。 它被执行。 在循环连接中,CTE被执行多次。 #temp已实现,因此仅运行一次。
检查此QnA并通过SQL Server MVP Gail Shaw进行响应:
http://www.sqlservercentral.com/Forums/Topic415829-338-1.aspx
简而言之,它说CTE就像临时视图一样 ,当您检查执行计划时,它会内联到查询中。 TempTable是在tempDB中创建的表 。
表比视图快(在您的情况下是递归视图)。 希望这可以解释两种方法之间的性能差异。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.