●存儲過程比sql語句慢

      今天碰到一個問題,有個存儲過程執行須要1分鐘,可是把存儲過程複製出來,將參數賦值,而後執行,只要6秒。後來終於發現是Parameter sniffing問題。sql

原存儲過程:ide

 

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在存儲過程執行以前都會制定一個執行計劃。spa

 

從網上找到的解決方式:code

一、用變量替換掉參數(已驗證,舉例以下)blog

二、將受影響的sql語句隱藏起來,好比:input

   a) 將受影響的sql語句放到某個子存儲過程當中,好比咱們在@thedate設置成爲今天后再調用一個字存儲過程將@thedate做爲參數傳入就能夠了。event

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

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

 

使用第一種方法修改後:cli

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
相關文章
相關標籤/搜索