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

mas*_*ani 23 sql t-sql sql-server performance

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

Qua*_*noi 21

派生表是一种逻辑结构.

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

临时表是物理构造.它是一个tempdb创建并使用值填充的表.

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

例如,每次使用时都会(并且很可能会)重新评估CTE(公共表表达式)SQL Server.这个查询:

WITH    q (uuid) AS
        (
        SELECT  NEWID()
        )
SELECT  *
FROM    q
UNION ALL
SELECT  *
FROM    q
Run Code Online (Sandbox Code Playgroud)

最有可能产生两种不同NEWID()的.

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

另一方面,这个查询:

SELECT  *
FROM    (
        SELECT  *, ROW_NUMBER() OVER (ORDER BY id) AS rn
        FROM    master
        ) q
WHERE   rn BETWEEN 80 AND 100
Run Code Online (Sandbox Code Playgroud)

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


onu*_*ade 10

这取决于具体情况.

派生表的优点:

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

  2. 派生表仅在查询执行计划方面"存在" - 它纯粹是一个逻辑构造.真的没有桌子.

临时表的优点

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

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


Jim*_*ark 5

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

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