为什么更快地插入和加入#temp表?

Jos*_*gry 12 sql t-sql sql-server sql-server-2005

我有一个看起来像的查询

SELECT
 P.Column1,
 P.Column2,
 P.Column3,
 ...
 (
   SELECT
       A.ColumnX,
       A.ColumnY,
       ...
   FROM
      dbo.TableReturningFunc1(@StaticParam1, @StaticParam2) AS A
   WHERE
      A.Key = P.Key
   FOR XML AUTO, TYPE  
 ),
 (
   SELECT
       B.ColumnX,
       B.ColumnY,
       ...
   FROM
      dbo.TableReturningFunc2(@StaticParam1, @StaticParam2) AS B
   WHERE
      B.Key = P.Key
   FOR XML AUTO, TYPE  
 )
FROM
(
   <joined tables here>
) AS P
FOR XML AUTO,ROOT('ROOT') 
Run Code Online (Sandbox Code Playgroud)

P具有~5000行A和B~4000行

此查询的运行时性能约为10 +分钟.

但是将它更改为:

SELECT
 P.Column1,
 P.Column2,
 P.Column3,
 ...
INTO #P

SELECT
 A.ColumnX,
 A.ColumnY,
 ...
INTO #A     
FROM
 dbo.TableReturningFunc1(@StaticParam1, @StaticParam2) AS A

SELECT
 B.ColumnX,
 B.ColumnY,
 ...
INTO #B     
FROM
 dbo.TableReturningFunc2(@StaticParam1, @StaticParam2) AS B


SELECT
 P.Column1,
 P.Column2,
 P.Column3,
 ...
 (
   SELECT
       A.ColumnX,
       A.ColumnY,
       ...
   FROM
      #A AS A
   WHERE
      A.Key = P.Key
   FOR XML AUTO, TYPE  
 ),
 (
   SELECT
       B.ColumnX,
       B.ColumnY,
       ...
   FROM
      #B AS B
   WHERE
      B.Key = P.Key
   FOR XML AUTO, TYPE  
 )
FROM #P AS P
FOR XML AUTO,ROOT('ROOT')      
Run Code Online (Sandbox Code Playgroud)

具有~4秒的性能.

这没有多大意义,因为看起来插入临时表然后默认情况下连接的成本应该更高.我倾向于SQL正在使用子查询执行错误的"连接"类型,但也许我错过了它,没有办法指定连接类型用于相关子查询.

有没有办法通过索引和/或提示使用#temp tables/@ table变量来实现这一目的?

编辑:请注意,dbo.TableReturningFunc1和dbo.TableReturningFunc2是内联TVF,而不是多语句,或者它们是"参数化"视图语句.

Qua*_*noi 16

您的程序正在重新评估P.

您对临时表执行的操作实际上是缓存存储过程生成的结果集,从而无需重新评估.

插入临时表很快,因为它不会生成redo/ rollback.

连接也很快,因为具有稳定的结果集允许使用a Eager Spool或a 创建临时索引Worktable

您可以使用CTE's 来重用没有临时表的过程,但为了提高效率,SQL Server需要实现结果CTE.

您可以尝试使用ORDER BY子查询内部强制执行此操作:

WITH    f1 AS
        (
        SELECT  TOP 1000000000
                A.ColumnX,
                A.ColumnY
        FROM    dbo.TableReturningFunc1(@StaticParam1, @StaticParam2) AS A
        ORDER BY
                A.key
        ),
        f2 AS
        (
        SELECT  TOP 1000000000
                B.ColumnX,
                B.ColumnY,
        FROM    dbo.TableReturningFunc2(@StaticParam1, @StaticParam2) AS B  
        ORDER BY
                B.Key
        )
SELECT  …
Run Code Online (Sandbox Code Playgroud)

,这可能导致Eager Spool优化器生成.

然而,这远非得到保证.

保证的方法是OPTION (USE PLAN)在查询中添加一个并将correspondenceind包装CTESpool子句中.

请参阅我的博客中有关如何执行此操作的条目:

这很难维护,因为每次重写查询时都需要重写计划,但这样做效果很好而且效率很高.

但是,使用临时表会更容易.