查询运行速度快,存储过程缓慢 - 多次尝试

时间:2016-12-13 16:19:58

标签: sql-server stored-procedures

我在SQL Server 2014上有一个存储过程,当使用硬编码的params直接运行查询时,它会立即运行。 当它运行存储过程时需要很长时间或超时。

在选择查询中出现的参数位于前1位

  , ISNULL((SELECT TOP 1 block_score FROM block_states BS WHERE BS.block_id = defined_blocks.id AND BS.user_name = @local_userName AND BS.orgId = @local_orgId AND BS.assessment_key = 0 ), 'NONE' )

导致问题,因为我在存储过程中硬编码了这些参数并且它几乎立即运行。

我已经阅读了很多关于parameter sniffingQuery runs fast, but runs slow in stored procedure中的建议,并尝试了一些事情;我已将参数设为本地参数 我也试过添加

OPTION(RECOMPILE)

并尝试运行

exec sp_updatestats 

但是所有人似乎都没有或没有什么区别。

存储过程如下:

     @userName NVARCHAR(100), @orgId NVARCHAR(100),@ chartId INT
AS



    DECLARE @definedchartBlocks TABLE(
        chartId INT,
        sectId BIGINT,
        subsectId BIGINT,
        blockId BIGINT,
        blockScore NVARCHAR(10)

    )
        Declare  @local_userName NVARCHAR(100), @local_orgId NVARCHAR(100), @local_chartId INT
        select @local_userName=@userName, @local_orgId=@orgId,@local_chartId=@chartId /*attempt to speed up stp*/


    INSERT INTO @definedchartBlocks

    SELECT      
        defined_sects.chart_id
        , defined_subsects.sect_id
        , defined_blocks.subsect_id
        , defined_blocks.id AS blockId

        , ISNULL((SELECT TOP 1 block_score FROM block_states BS WHERE BS.block_id = defined_blocks.id AND BS.user_name = @local_userName AND BS.orgId = @local_orgId AND BS.assessment_key = 0 ), 'NONE' )
    FROM         
        defined_subsects 
        INNER JOIN
        defined_sects ON defined_subsects.sect_id = defined_sects.id 
        INNER JOIN
        defined_blocks ON defined_subsects.id = defined_blocks.subsect_id
    WHERE     
        (defined_sects.chart_id = @local_chartId)

OPTION(RECOMPILE)

    IF EXISTS (
    SELECT      
            MAX(definedchartBlocks.blockScore)
    FROM         
        @definedchartBlocks definedchartBlocks
    WHERE
        definedchartBlocks.blockScore = 'AMBER' OR definedchartBlocks.blockScore = 'RED' OR definedchartBlocks.blockScore = 'NONE' OR definedchartBlocks.blockScore = '' OR definedchartBlocks.blockScore IS NULL

    GROUP BY 
        definedchartBlocks.blockScore
    )
    BEGIN

        SELECT 0 AS chartCompleted
    END
    ELSE
    BEGIN
        SELECT 1 AS chartCompleted
    END

1 个答案:

答案 0 :(得分:4)

SQL Server在大多数情况下确实做了很好的隐式转换,但有时它可能会使查询陷入困境。您提到硬编码值会立即返回,但使用变量则不会。

使用变量时,请确保数据类型与列的数据类型匹配。我怀疑问题是,当您的列为NVARCHAR (100)时,您的变量为VARCHAR (50)

查看这可能是一个问题的另一种方法是查看查询计划 - 在这种情况下,您可能会看到类似于以下内容的警告:

  

表达式中的类型转换(CONVERT_IMPLICIT(...))可能影响" SeekPlan"在查询计划选择中