Sql-Server

如何在此儲存過程中添加選項(重新編譯)?

  • September 19, 2018

在我目前的環境中,我有很多儲存過程的實例,如下圖所示,其中將一堆參數傳遞給過程,然後在過程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

不,這看起來不適合重新編譯。從程式碼來看,它看起來activityId是獨一無二的,並且會產生一個簡單的計劃,因此無論傳遞的參數如何,您都將獲得相同的計劃。如果您的情況不是這種情況,請將 DDL 添加到您的問題中。

如果最優計劃根據傳遞的實際參數值不同(因為這些在 WHERE/JOIN 子句中使用並且最優計劃相應地變化),您可以OPTION(RECOMPILE)在特定問題查詢中指定查詢提示以避免重用非平凡計劃。但是,如果查詢非常頻繁地執行,編譯成本可能會超過收益。在這種情況下,最好使用OPTIMIZE FOR提示或使用查詢儲存(或計劃指南)來強制執行特定計劃。

引用自:https://dba.stackexchange.com/questions/218011