哪一个具有更好的性能:派生表或临时表

时间:2010-02-24 13:47:30

标签: sql sql-server performance tsql

有时我们可以使用派生表和临时表编写查询。我的问题是哪一个更好?为什么呢?

4 个答案:

答案 0 :(得分:21)

派生表是一种逻辑结构。

它可以存储在tempdb中,在运行时通过每次访问时重新评估基础语句,甚至根本不进行优化。

临时表是物理构造。它是tempdb中创建并使用值填充的表。

哪一个更好取决于它们使用的查询,用于派生表的语句以及许多其他因素。

例如,CTE中的SQL Server(公用表表达式)可以(并且很可能将)在每次使用时重新评估。这个查询:

WITH    q (uuid) AS
        (
        SELECT  NEWID()
        )
SELECT  *
FROM    q
UNION ALL
SELECT  *
FROM    q

很可能会产生两个不同的NEWID()

在这种情况下,应该使用临时表,因为它可以保证其值保持不变。

另一方面,这个查询:

SELECT  *
FROM    (
        SELECT  *, ROW_NUMBER() OVER (ORDER BY id) AS rn
        FROM    master
        ) q
WHERE   rn BETWEEN 80 AND 100
对于派生表,

更好,因为使用临时表将需要从master获取所有值,而此解决方案将使用100上的索引扫描第一个id记录

答案 1 :(得分:10)

这取决于具体情况。

派生表的优点:

  1. 派生表是较大的单个查询的一部分,将在查询的其余部分的上下文中进行优化。如果查询优化有助于提高性能(通常情况下,除了一些例外情况),这可能是一个优势。示例:如果您填充临时表,然后在第二个查询中使用结果,您实际上将数据库引擎绑定到一个执行方法(完整地运行第一个查询,保存整个结果,运行第二个查询)使用派生表,优化器可能能够找到更快的执行方法或访问路径。

  2. 根据查询执行计划,派生表仅“存在” - 它纯粹是一个逻辑构造。确实没有桌子。

  3. 临时表的优点

    1. 表“存在” - 也就是说,它实现为一个表,至少在内存中,它包含结果集并且可以重复使用。

    2. 在某些情况下,当您必须对数据执行一些精细的转换时,可以提高性能或减少阻塞 - 例如,如果要从基表中获取“快照”行集,忙,然后对该集进行一些复杂的计算,如果你从基表中获取行并尽快解锁它,那么可以减少争用,然后独立完成工作。在某些情况下,真实临时表的开销相对于并发的优势而言很小。

答案 2 :(得分:5)

我想在这里添加一个轶事,因为它引导我对接受的答案提出相反的建议。我同意接受的答案中提出的想法,但它主要是理论上的。我的经验使我建议临时表而不是派生表,公用表表达式和表值函数。在我们开始处理更大的结果集和/或更复杂的查询之前,我们广泛使用派生表和公用表表达式,并基于与已接受答案一致的思想取得了很大成功。然后我们发现优化器没有很好地优化派生表或CTE。

我今天看了一个例子,跑了10点15分。我将派生表中的结果插入临时表,并在主查询中加入临时表,总时间下降到0:03。通常当我们看到一个重大的性能问题时,我们可以通过这种方式快速解决出于这个原因,我建议使用临时表,除非您的查询相对简单,并且您确定它不会处理大型数据集。

答案 3 :(得分:0)

最大的区别在于您可以将包含主键的约束放在临时表上。对于大(我的意思是数百万条记录),有时你可以通过临时获得更好的性能。我有需要5个连接的密钥查询(每个连接碰巧类似)。 2个连接的性能还可以,然后第三个性能变差,查询计划变得疯狂。即使有提示我也无法更正查询计划。尝试将连接重组为派生表并且仍然存在相同的性能问题。使用临时表可以创建主键(然后当我在PK上填充第一个排序时)。当SQL可以加入5个表并使用PK时,性能从几分钟到几秒。我希望SQL支持对派生表和CTE的约束(即使只是PK)。