我有一个可怕的执行存储过程。 当我声明一个变量,设置它的值,然后在where子句中的语句需要一个多小时才能运行在使用它。 当我硬编码在不到一秒钟的运行where子句中的变量。
我开始寻找到什么是通过执行计划不妥。 它看起来像当我尝试通过它的一些声明的变量执行计划包装箱一些哈希匹配,因为它从一个使用UNION和公用表表达式的视图选择值。
/************* Begin of Stored Procedure ***************/ CREATE PROCEDURE GetFruit @ColorId bigint, @SeasionId bigint WITH RECOMPILE AS BEGIN SELECT A.Name FROM [Apple_View] A /* This is the view down below */ INNER JOIN [Fruit] F ON ( F.ColorId = @ColorId AND A.FruitId = F.FruitId) WHERE (A.ColorId = @ColorId AND A.SeasonId = @SeasonId) END /************* End of Stored Procedure ***************/ /************* Begin of View ***************/ WITH Fruits (FruitId, ColorId, SeasonId) AS ( -- Anchor member SELECT F.FruitId ,F.ColorId ,F.SeasonId FROM (( SELECT DISTINCT EF.FruitId ,EF.ColorId ,EF.SeasonId ,EF.ParentFruitId FROM ExoticFruit EF INNER JOIN Fruit FR ON FR.FruitId = EF.FruitId UNION SELECT DISTINCT SF.FruitId ,SF.ColorId ,SF.SeasonId ,SF.ParentFruitId FROM StinkyFruit SF INNER JOIN Fruit FR ON FR.FruitId = SF.FruitId UNION SELECT DISTINCT CF.FruitId ,CF.ColorId ,CF.SeasonId ,CF.ParentFruitId FROM CrazyFruit CF INNER JOIN Fruit FR ON FR.FruitId = CF.FruitId )) f UNION ALL -- Recursive Parent Fruit SELECT FS.FruitId ,FS.ColorId ,FS.SeasonId ,FS.ParentFruitId FROM Fruits FS INNER JOIN MasterFruit MF ON MF.[ParentFruitId] = fs.[FruitId] ) SELECT DISTINCT FS.FruitId ,FS.ColorId ,FS.SeasonId FROM Fruits FS /************* End of View ***************/ /* To Execute */ EXEC GetFruit 1,3
如果我使用的设定值运行存储过程花费了一个多小时,这里是执行计划。
如果我运行存储过程移除声明和设定值,只是Where子句设置为在它不到一秒钟的运行,这里下面的语句是执行计划:
WHERE(A.ColorId = 1 AND A.SeasonId = 3)
请注意硬编码的变量是如何使用索引,而首先使用哈希集合。 这是为什么? 为什么从该声明的变量工作不同的where子句中的硬编码值?
-------这就是最后用@ user1166147的帮助下进行------
我改变了存储过程使用sp_executesql的。
CREATE PROCEDURE GetFruit @ColorId bigint, @SeasionId bigint WITH RECOMPILE AS BEGIN DECLARE @SelectString nvarchar(max) SET @SelectString = N'SELECT A.Name FROM [Apple_View] A /* This is the view down below */ INNER JOIN [Fruit] F ON ( F.ColorId = @ColorId AND A.FruitId = F.FruitId) WHERE (A.ColorId = ' + CONVERT(NVARCHAR(MAX), @ColorId) + ' AND A.SeasonId = ' + CONVERT(NVARCHAR(MAX), @SeasonId) + ')' EXEC sp_executesql @SelectString END