繁体   English   中英

SQL 2005 CTE与TEMP表在其他表的连接中使用时的性能

[英]SQL 2005 CTE vs TEMP table Performance when used in joins of other tables

我有一个复杂的查询,我需要在后续查询(实际更新语句)中使用。 我尝试过使用CTE和临时表。 使用CTE的性能与临时表方法相比非常糟糕。 它像15秒对毫秒。 为了简化测试而不是在后续查询中加入CTE / Temp表,我只是从中选择了*。 在那种情况下,他们执行相同的操作

我已经查看了两种方法的执行计划,这两种方法都使用了后续查询中的连接,然后只需选择*。 与简单选择查询计划大致相同,但在后续选择连接时查询计划不是。 具体来说,用于创建和填充临时表的查询计划部分保持不变,而用于创建和填充CTE的查询计划部分随后在具有连接的查询中使用时会发生显着变化。

我的问题是为什么CTE的创建和填充的查询计划根据临时表的后续使用方式而改变。 同样在什么情况下,CTE会比临时表产生更好的性能?

*注意我也使用了表变量,它与临时表方法相当。

谢谢

CTE只是查询的别名。

它可能(或可能不)每次使用时重新运行。

没有干净的方法来强制SQL Server CTE实现(比如Oracle的/*+ MATERIALIZE */ ),你必须做这样的脏技巧:

如果在仅需要一次评估的计划(如HASH JOINMERGE JOIN等)中使用, CTE可以提高性能。

在这些场景中,哈希表将直接从CTE构建,而使用临时表将需要评估CTE ,将结果拉入临时表并再次读取临时表。

你问的是一个复杂的问题,所以你得到一个复杂的答案:这取决于你。 (我讨厌那个回应)。

但是,严重的是,它与优化程序如何选择数据计划(您已经知道)有关; 临时表或变量类似于永久结构,因为执行计划将首先执行与填充该结构相关联的操作,然后在后续操作中使用该结构。 CTE不是临时表; CTE的使用在后续操作使用之前不会计算,因此使用会影响计划的优化方式。

CTE是针对可重用性和维护问题而实施的,不一定是性能; 然而,在许多情况下(如递归),它们将比传统的编码方法表现更好。

我发现通常重复的CTE没有性能改进。

因此,例如,如果您使用CTE填充表,然后使用相同的CTE在以后的查询中加入,则没有任何好处。 不幸的是,CTE不是快照,它们必须重复使用才能在两个单独的语句中使用,因此它们往往被评估两次。

我经常使用内联TVF(可能包含CTE)而不是CTE,它允许正确的重复使用,并且不比我的SP中的CTE更好或更差。

此外,我还发现,如果第一步改变统计信息,执行计划可能会很糟糕,因为第二步的执行计划总是不准确,因为在运行任何步骤之前对其进行评估。

在这种情况下,我考虑手动存储中间结果,确保它们被正确编入索引并将流程拆分为多个SP并添加WITH RECOMPILE以确保后续SP具有对他们实际将要运行的数据有利的计划上。

我尝试用大表中的过滤器简单选择创建CTE然后3次subqueried它。

之后对临时表执行相同操作。

结果是CTE耗时70% - 临时表耗时30%。 因此临时表对于该解决方案更好。

我不认为CTE只使用选定的查询创建临时表,但是3次选择一个大表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM