代码之家  ›  专栏  ›  技术社区  ›  Gratzy

SQL 2005 CTE与临时表性能(当用于其他表的联接时)

  •  12
  • Gratzy  · 技术社区  · 15 年前

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

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

    我的问题是,为什么创建和填充CTE的查询计划会因随后如何使用而发生变化,而临时表则不会。此外,在什么情况下,CTE会比临时表产生更好的性能?

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

    谢谢

    4 回复  |  直到 15 年前
        1
  •  9
  •   Stuart Ainsworth    15 年前

    你问了一个复杂的问题,所以你得到了一个复杂的答案:这要看情况(我讨厌这种反应)。

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

    CTE的实施是为了可重用性和维护问题,不一定是为了性能;然而,在许多情况下(如递归),它们的性能将优于传统的编码方法。

        2
  •  13
  •   Quassnoi    15 年前

    CTE 只是查询的别名。

    它可能(也可能不)在每次使用时都会重新运行。

    CTE 物质化 SQL Server /*+ MATERIALIZE */ ),你必须做这样肮脏的把戏:

    CTE HASH JOIN , MERGE JOIN

    在这些场景中,哈希表将直接从 CTE ,将结果拉入临时表并再次读取临时表。

        3
  •  2
  •   Cade Roux    15 年前

    我发现重复的CTE通常不会得到性能改进。

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

    此外,我还发现,如果第一步改变了统计信息,那么第二步的执行计划总是不准确的,因为它是在任何步骤运行之前进行评估的,那么执行计划可能是不好的。

        4
  •  1
  •   marc_s HarisH Sharma    7 年前

    我试着用大表中的简单选择过滤器创建CTE 然后3次子查询它。

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

    因此,临时表更适合该解决方案。

    我不认为CTE只使用选定的查询生成临时表,而是3次将select生成一个大表。