Mar*_*lli 0 sql-server stored-procedures optimization sql-server-2016 parameter-sniffing
在我现在的环境中,我有很多存储过程的实例,就像下图所示的那样,将一堆参数传递给过程,然后在过程select exists
中运行a ,并根据结果运行不同的逻辑路径在存储过程中。
我对以下程序有几个问题:
1)它是参数嗅探的好选择吗?
2)我怎么能option(recompile)
在代码中添加?
在代码中添加选项(重新编译)与使用重新编译创建存储过程之间存在差异。
option(recompile)
如果可能的话,我会更热衷于。
ALTER PROCEDURE [dbo].[usp_upd_activity]
@activityId INT,
@title VARCHAR(100),
@description VARCHAR(MAX),
@inclusions VARCHAR(MAX),
@locationId INT,
@imageUriMain VARCHAR(255),
@uploadToBucket VARCHAR(200),
@path VARCHAR(200)
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRAN
BEGIN TRY
DECLARE @documentId INT
IF NOT EXISTS (SELECT 1
FROM document
WHERE activityId = @activityId)
BEGIN
INSERT INTO document
( [uploadToBucket], [path], [activityId])
VALUES (@uploadToBucket, @path, @activityId)
SET @documentId = SCOPE_IDENTITY();
END
ELSE
BEGIN
UPDATE document
SET uploadToBucket = @uploadToBucket,
[path] = @path,
activityId = @activityId
WHERE activityId = @activityId
SET @documentId =
(SELECT documentId
FROM document
WHERE activityId = @activityId)
END
UPDATE activity
SET title = @title,
description = @description,
inclusions = @inclusions,
locationId = @locationId,
imageUriMain = IsNull(@imageUriMain, imageUriMain),
documentId = @documentId
WHERE activityId = @activityId
COMMIT
END TRY
BEGIN CATCH
DECLARE @ErrorMessage nvarchar(max),
@ErrorSeverity int,
@ErrorState int;
SELECT @ErrorMessage = ERROR_MESSAGE() + ' Line ' +
cast(ERROR_LINE() as nvarchar(5)),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
IF @@TRANCOUNT > 0
ROLLBACK;
RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH
END
Run Code Online (Sandbox Code Playgroud)
不,这看起来不是重新编译的好选择。从代码来看,它看起来activityId
是独一无二的,并且会产生一个简单的计划,因此无论传递的参数如何,您都将获得相同的计划。如果您的情况不是这种情况,请将 DDL 添加到您的问题中。
如果最优计划根据传递的实际参数值而有所不同(因为这些用于 WHERE/JOIN 子句中,并且最优计划会相应变化),您可以OPTION(RECOMPILE)
在特定问题查询上指定查询提示,以避免重复使用非平凡计划。但是,如果查询执行得非常频繁,则编译成本可能会超过收益。在这种情况下,最好使用OPTIMIZE FOR
提示或使用查询存储(或计划指南)来强制执行特定计划。