SQL 2014 Query在sp_executesql中的运行速度比在普通查询中快得多

时间:2018-01-25 13:21:23

标签: sql sql-server-2014

非常奇怪的问题,我看起来但最好我可以看到这不是一个已知的问题。

我正在调试其他人为SSRS报告编写的查询。

从SSRS运行时返回13,730行。我在SQL事件探查器中捕获了此查询执行,然后在SSMS中运行它,返回11,940行。报告对结果集没有任何作用,它只显示每一行。

然后我从sp_executesql中取出查询并将sp_executesql参数转换为普通参数。当这在SSMS中运行时,查询只是无休止地使用CXPACKET等待类型进行旋转。

我不明白同一个查询实际上如何通过运行它来获得如此截然不同的结果和执行计划。

我无法在此复制整个查询,但其要点是:

/* Example 1 

    This returns different results when run from the report (SQL Server Reporting Services 2014) as opposed to when run in SQL Server Management Studio. The actual execution from SSRS was captured using profiler

    Either execution completed in about 15 seconds.

*/

exec sp_executesql N'

CREATE TABLE #tmpTable (
    field1 varchar(250),
    field2 int,
    field3 varchar(max)
)

Insert into #tmpTablea
    SELECT
        somestuff as field1,
        someotherstuff as field2,
        morestuff as field3
    FROM
        RealTable
    WHERE
        somestuff = ''stuff that matters for the first query''
    AND
        otherstuff = @param1


Insert into #tmpTable
    SELECT
        somestuff as field1,
        someotherstuff as field2,
        morestuff as field3
    FROM
        RealTable2
    WHERE
        somestuff = ''stuff that matters for the second query''
    AND
        otherstuff = @param2

    SELECT * FROM #tmpTable

    ',N'@param1 nvarchar(4000),@param2 nvarchar(4000)',@param1=N'value1',@param2=N'value2'


/* Example 2 

    This one just runs forever, I cancelled it after 15 minutes.

*/

Declare @param1 nvarchar(4000),
        @param2 nvarchar(4000)

SELECT @param1  = 'value1',
        @param2 = 'value2'

CREATE TABLE #tmpTable (
    field1 varchar(250),
    field2 int,
    field3 varchar(max)
)

Insert into #tmpTable
    SELECT
        somestuff as field1,
        someotherstuff as field2,
        morestuff as field3
    FROM
        RealTable
    WHERE
        somestuff = ''stuff that matters for the first query''
    AND
        otherstuff = @param1


Insert into #tmpTable
    SELECT
        somestuff as field1,
        someotherstuff as field2,
        morestuff as field3
    FROM
        RealTable2
    WHERE
        somestuff = ''stuff that matters for the second query''
    AND
        otherstuff = @param2

    SELECT * FROM #tmpTable

1 个答案:

答案 0 :(得分:1)

有趣。您可能已经发现了一些未发布的有关SQL-Server内部行为的内容。

您提到当您在没有sp_executesql的情况下运行查询时,它会使用CXPACKET等待类型进行旋转。这意味着查询优化器并行化了您的查询。 CXPACKET等待类型是运行查询的进程交换信息时发生的情况。

当你使用sp_executesql时,它只是立即运行,这表明sp_execautesql(没有CXPACKET等待类型)没有并行化你的查询,或者没有将它并行化。

您可以轻松地测试这个理论。在不使用sp_executesql的版本中的每个语句的末尾,放置:

选项(MAXDOP 0);

这实际上告诉Sql-Server只使用一个核心,并且应该保证没有CXPACKET等待。

如果这有帮助,那么用MAXDOP 1,MAXDOP 2等进行测试......

注意:一般情况下,查询优化器可以很好地确定何时进行并行化以及这样做的程度(即,它确定了最佳MAXDOP值),但有时候,它并不是,经过一些实验后,这样的提示可以加快速度。