如何在此存储过程中添加选项(重新编译)?

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)

Dan*_*man 5

不,这看起来不是重新编译的好选择。从代码来看,它看起来activityId是独一无二的,并且会产生一个简单的计划,因此无论传递的参数如何,您都将获得相同的计划。如果您的情况不是这种情况,请将 DDL 添加到您的问题中。

如果最优计划根据传递的实际参数值而有所不同(因为这些用于 WHERE/JOIN 子句中,并且最优计划会相应变化),您可以OPTION(RECOMPILE)在特定问题查询上指定查询提示,以避免重复使用非平凡计划。但是,如果查询执行得非常频繁,则编译成本可能会超过收益。在这种情况下,最好使用OPTIMIZE FOR提示或使用查询存储(或计划指南)来强制执行特定计划。