●存儲過程比sql語句慢


      今天碰到一個問題,有個存儲過程執行需要1分鍾,但是把存儲過程復制出來,將參數賦值,然后執行,只要6秒。后來終於發現是Parameter sniffing問題。

原存儲過程:

 

IF ( OBJECT_ID('sp_yp_jxctj', 'P') IS NOT NULL )
    DROP PROC sp_yp_jxctj;
GO
 
/*========================================================  
描述:
系統:
引用:
輸入:
輸出:
備注:
修改記錄:
==========================================================*/
 
CREATE PROC sp_yp_jxctj
    @startDate  VARCHAR(50) ,   --開始時間
    @endDate    VARCHAR(50) ,   --結束時間
    @inputCode  VARCHAR(24) ,   --輸入碼
    @deptCode   VARCHAR(20) ,   --科室代碼
    @drugType   CHAR(2) ,       --葯品類型
    @drugAttr   VARCHAR(20) ,   --葯品屬性
    @dosage     VARCHAR(20) ,   --劑型
    @drugState  INT ,           --葯品狀態
    @rate       INT             --零差率
AS
    BEGIN
    ----------------------------
    --內容省略
    ----------------------------
    end;
View Code

    在SQL Server中有一個叫做 “Parameter sniffing”的特性。SQL Server在存儲過程執行之前都會制定一個執行計划。

 

從網上找到的解決方式:

1、用變量替換掉參數(已驗證,舉例如下)

2、將受影響的sql語句隱藏起來,比如:

   a) 將受影響的sql語句放到某個子存儲過程中,比如我們在@thedate設置成為今天后再調用一個字存儲過程將@thedate作為參數傳入就可以了。

   b) 使用sp_executesql來執行受影響的sql。執行計划不會被執行,除非sp_executesql語句執行完。

   c) 使用動態sql(”EXEC(@sql)”來執行受影響的sql。

 

使用第一種方法修改后:

IF ( OBJECT_ID('sp_yp_jxctj', 'P') IS NOT NULL )
    DROP PROC sp_yp_jxctj;
GO
 
/*========================================================  
描述:
系統:
引用:
輸入:
輸出:
備注:
修改記錄:
==========================================================*/
 
CREATE PROC sp_yp_jxctj
    @startDate VARCHAR(50) ,    --開始時間
    @endDate VARCHAR(50) ,      --結束時間
    @inputCode VARCHAR(24) ,    --輸入碼
    @deptCode VARCHAR(20) ,     --科室代碼
    @drugType CHAR(2) ,         --葯品類型
    @drugAttr VARCHAR(20) ,     --葯品屬性
    @dosage VARCHAR(20) ,       --劑型
    @drugState INT ,            --葯品狀態
    @rate INT                   --零差率
AS
    BEGIN
--用變量替換掉參數,以防出現“Parameter sniffing”問題
        DECLARE @deptType INT ,
            @startDate1 VARCHAR(50) = @startDate ,  --開始時間
            @endDate1   VARCHAR(50) = @endDate ,    --結束時間
            @inputCode1 VARCHAR(24) = @inputCode ,  --輸入碼
            @deptCode1  VARCHAR(20) = @deptCode ,   --科室代碼
            @drugType1  CHAR(2)     = @drugType ,   --葯品類型
            @drugAttr1  VARCHAR(20) = @drugAttr ,   --葯品屬性
            @dosage1    VARCHAR(20) = @dosage ,     --劑型
            @drugState1 INT         = @drugState ,  --葯品狀態
            @rate1      INT         = @rate;        --零差率
 
    ----------------------------
    --內容省略
    ----------------------------
    END;        
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM