为什么使用临时表与表变量会提高此查询的速度?

时间:2014-01-06 21:53:34

标签: sql sql-server sql-server-2008 temp-tables

我目前遇到查询的性能问题(比下面的示例更复杂)。最初查询将运行并占用30秒,然后当我关闭使用表变量来使用临时表时,速度会降低到几秒钟。

这是一个使用表变量的精简版:

-- Store XML into tables for use in query
DECLARE @tCodes TABLE([Code] VARCHAR(100))

INSERT INTO
    @tCodes
SELECT 
    ParamValues.ID.value('.','VARCHAR(100)') AS 'Code'
FROM 
    @xmlCodes.nodes('/ArrayOfString/string') AS ParamValues(ID)


SELECT
    'SummedValue' = SUM(ot.[Value])
FROM
    [SomeTable] st (NOLOCK)
JOIN
    [OtherTable] ot (NOLOCK)
    ON  ot.[SomeTableID] = st.[ID]
WHERE
    ot.[CodeID] IN (SELECT [Code] FROM @tCodes) AND 
    st.[Status] = 'ACTIVE' AND
    YEAR(ot.[SomeDate]) = 2013 AND  
    LEFT(st.[Identifier], 11) = @sIdentifier

这是带有临时表的版本,它可以更快地执行:

SELECT 
    ParamValues.ID.value('.','VARCHAR(100)') AS 'Code'
INTO
    #tCodes
FROM 
    @xmlCodes.nodes('/ArrayOfString/string') AS ParamValues(ID)


SELECT
    'SummedValue' = SUM(ot.[Value])
FROM
    [SomeTable] st (NOLOCK)
JOIN
    [OtherTable] ot (NOLOCK)
    ON  ot.[SomeTableID] = st.[ID]
WHERE
    ot.[CodeID] IN (SELECT [Code] FROM #tCodes) AND 
    st.[Status] = 'ACTIVE' AND
    YEAR(ot.[SomeDate]) = 2013 AND  
    LEFT(st.[Identifier], 11) = @sIdentifier

我对性能的问题通过更改解决了,但我只是不明白为什么它解决了这个问题,并且更愿意知道原因。它可能与查询中的其他内容有关,但我在存储过程中所做的更改(更复杂)是从使用表变量切换到使用临时表。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

深入研究表变量和#temp表之间的差异和相似之处{/ 3}}。

关于你展示的两个查询(未编制索引的表变量与未索引的临时表),我想到了三种可能性。

  1. INSERT ... SELECT表变量始终是串行的。可以为临时表并行化SELECT
  2. 临时表可以为其自动创建列统计直方图。
  3. 通常假设表变量的基数为0(当表为空时编译它们)
  4. 从您显示的代码(3)看起来似乎是最可能的解释。

    这可以通过在填充表变量后使用OPTION (RECOMPILE)重新编译语句来解决。