将所有子选择切换到临时表并加入影响性能?

时间:2014-01-10 14:09:07

标签: sql-server performance tsql temp-tables subquery

我们的一个客户希望为他们的SQL存储过程引入一个新的编码标准,该标准规定所有子选择将被临时表和连接替换。他们引用可读性作为改变的原因。

我对SQL性能调优的细节并不是很了解,但是这一点让我觉得它会导致性能问题。我是对的吗?

我们正在使用MS SQL,如果这有所不同。

2 个答案:

答案 0 :(得分:2)

我担心这个问题可能过于宽泛,需要解释。

通常,使用临时表进行中间结果是绕过SQL Server的查询优化器。临时表的创建会产生开销,创建表然后再读取数据。例如,考虑以下只使用子查询来定义各种列别名的查询:

select col3 + 1
from (select col2 * 2 as col3
      from (select col1/100 as col2
            from (select col*col as col1
                  from a
                 ) b
           ) c
     ) d

子查询的这种结构相当常见,因为SQL不允许在与其定义相同的级别使用列别名。实现中间表会对性能产生很大影响。

另一方面,有些情况下查询的结构可能是:

with cte as (
      <complex query here>
     )
select . . .
from cte cte1 join
     cte cte2
     on cte1.col = cte2.col;

在这种情况下,查询引擎实际上两次运行CTE的子查询。将结果存储在临时表中可能会提高性能。

我对临时表的最大反对意见是维护 - 具有讽刺意味的是客户想要使用它们。例如,更改查询可能会更改临时表的结构。在单个查询中,很明显要保留哪个以及要删除哪个。作为一堆临时表,您冒着创建不再需要的表的风险。

答案 1 :(得分:0)

根据数据以及子选择的使用方式,可能会提高性能或降低性能。相关子查询往往表现不佳,临时表或联接往往会提高性能。派生表可能比临时表更快,或者可能不依赖于返回的行数以及临时表是否已编制索引。所有这些还取决于您的特定数据库的设计以及查询的其余部分。有时表变量或表值函数可能是最佳选择。使用此标准会失去很多灵活性。

就我个人而言,我会向他们解释可能存在的问题以及创建子选择的其他方法。如果他们仍然想要这样做,那么请使用这个新标准,但是如果您需要对查询进行性能调整,请允许修改标准以使您违反该标准。如果它们将包含大量记录,也要确保索引临时表。