我在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 sniffing和Query 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
答案 0 :(得分:4)
SQL Server在大多数情况下确实做了很好的隐式转换,但有时它可能会使查询陷入困境。您提到硬编码值会立即返回,但使用变量则不会。
使用变量时,请确保数据类型与列的数据类型匹配。我怀疑问题是,当您的列为NVARCHAR (100)
时,您的变量为VARCHAR (50)
。
查看这可能是一个问题的另一种方法是查看查询计划 - 在这种情况下,您可能会看到类似于以下内容的警告:
表达式中的类型转换(CONVERT_IMPLICIT(...))可能影响" SeekPlan"在查询计划选择中