簡體   English   中英

SQL Server —提高游標速度

[英]SQL Server — Improve Speed of Cursor

我正在使用以下代碼檢查特定行的@act_value列是否在24.0以上,並使用游標遍歷表的每一行。 如果@act_value高於24.0,則將完成一些操作以及更新該條目並插入新條目。 就是說,查詢要花26分鍾才能運行(從下面提供此添加之前的0:16分鍾開始),並且可能占用大量資源。 是否有更好的配置可以加快此操作?

DECLARE cur_hours_check CURSOR
FOR
    SELECT 
       Period, Act_Batch_Time, Kg_Per_Hour, Total_QT_Produced, 
       Total_Possible_KG,
       --The columns not affected but need for inserting the shadow day
       Division, Region, Business_Region, Plant, Work_Center, DaysInMonth, 
       Total_Possible_Hours, Demonstrated_Capacity
    FROM 
       zt_Demonstrated_Capacity_Trend

OPEN cur_hours_check

DECLARE             --Cursor Variables Pulling data
    @period                   datetime
,   @act_hours                float
,   @over_hours               float
,   @Total_QT_Produced        float
,   @KG_per_hour              float
,   @Total_Possible_KG        float
--then the extra
,   @Division                 varchar(20)
,   @Region                   varchar(20)
,   @Business_Region          varchar(20)
,   @Plant                    varchar(40)
,   @Work_Center              varchar(40)
,   @DaysInMonth              float
,   @Total_Possible_Hours     float
,   @Demonstrated_Capacity    float

DECLARE             --Cursor Shadow variables:
    @shadow_period                 datetime 
,   @shadow_act_hours              float
,   @shadow_Total_QT_Produced      float
,   @shadow_Total_Possible_KG      float
,   @shadow_Percent_of_Total_Hours float

DECLARE             --Cursor adjusted first day variables
    @adj_act_hours                 float
,   @adj_Total_QT_Produced         float
,   @adj_Total_Possible_KG         float
,   @adj_Percent_of_Total_Hours    float

FETCH FROM cur_hours_check
    INTO @period, @act_hours, @KG_per_hour, @Total_QT_Produced, @Total_Possible_KG
   ,@Division, @Region, @Business_Region, @Plant, @Work_Center, @DaysInMonth, @Total_Possible_Hours, @Demonstrated_Capacity

WHILE @@FETCH_STATUS = 0
BEGIN

    IF @act_hours > 24.0
    BEGIN
    -- Setting the shadow period to carry over values relative to 24 hour time window
        SET @shadow_period = dateadd(dd, datediff(dd, 0, @period) + 1, 0) 
        SET @shadow_act_hours = @act_hours - 24.0
        SET @shadow_Total_QT_Produced = (@Total_QT_Produced - (@KG_per_hour * @shadow_act_hours))
        SET @shadow_Percent_of_Total_Hours = (@shadow_act_hours/24.0)*100

    -- Adjusting first period for 24 hour window of operation
        SET @adj_act_hours = 24.0
        SET @adj_Total_QT_Produced =  @Total_QT_Produced - (@KG_per_hour * 24.0)
        SET @adj_Total_Possible_KG = @Total_Possible_KG *(1-( @shadow_act_hours/@act_hours ))
        SET @adj_Percent_of_Total_Hours = 100

    -- now update that record, as well as insert the shadow day
        UPDATE zt_Demonstrated_Capacity_Trend
        SET Period = @period
        , Act_Batch_Time = 24.0
        , Total_QT_Produced = @adj_Total_QT_Produced
        , Total_Possible_KG = @adj_Total_Possible_KG
        , Kg_Per_Hour = @KG_per_hour
        , Percent_of_Total_Hours = @adj_Percent_of_Total_Hours
        , Division = @Division
        , Region = @Region
        , Business_Region = @Business_Region
        , Plant = @Plant
        , Work_Center = @Work_Center
        , DaysInMonth = @DaysInMonth
        , Total_Possible_Hours = @Total_Possible_Hours
        , Demonstrated_Capacity = @Demonstrated_Capacity
        WHERE CURRENT OF cur_hours_check 

    --Inserting the shadow record
        INSERT INTO [dbo].[zt_Demonstrated_Capacity_Trend](
        [Period]
        ,[Division]
        ,[Region]
        ,[Business_Region]
        ,[Plant]
        ,[Work_Center]
        ,[Kg_Per_Hour]
        ,[Total_QT_Produced]
        ,[Act_Batch_Time]
        ,[DaysInMonth]
        ,[Total_Possible_Hours]
        ,[Demonstrated_Capacity]
        ,[Total_Possible_KG]
        ,[Percent_of_Total_Hours])
        VALUES
        (@shadow_period
        ,@Division
        ,@Region
        ,@Business_Region
        ,@Plant
        ,@Work_Center
        ,@Kg_Per_Hour
        ,@shadow_Total_QT_Produced
        ,@shadow_act_hours
        ,@DaysInMonth
        ,@Total_Possible_Hours
        ,@Demonstrated_Capacity
        ,@adj_Total_Possible_KG
        ,@shadow_Percent_of_Total_Hours)
    END
    FETCH NEXT FROM cur_hours_check
    INTO @period, @act_hours, @KG_per_hour, @Total_QT_Produced, @Total_Possible_KG
   ,@Division, @Region, @Business_Region, @Plant, @Work_Center, @DaysInMonth, @Total_Possible_Hours, @Demonstrated_Capacity

END;

CLOSE       cur_hours_check
DEALLOCATE  cur_hours_check

使用TSQL進行預期的基於集合的操作,我已經對您使用的變量進行了修改,並在SQLFiddle上設置了一個示例,該示例通過使用余。 這是工作:

BEGIN TRAN
INSERT INTO zt_Demonstrated_Capacity_Trend (
        -- The Columns we care about modifying
        period, Act_Batch_Time, Total_QT_Produced, KG_per_hour, Total_Possible_KG, Percent_of_Total_Hours
        -- The rest that you aren't touching in your procedure
        , Division, Region, Business_Region, Plant, Work_Center, DaysInMonth, Total_Possible_Hours, Demonstrated_Capacity, over_hours
    )
SELECT
    -- Add a day equal to the rows we generate
      DATEADD(dd,ShadowDays, Period) AS Shadow_Period
    -- Hours we generate
    , ShadowHours AS Shadow_Hours
    -- Our Hours times the rate is total produced
    , Kg_Per_Hour * ShadowHours AS Shadow_Total_QT_Produced
    -- Unmodified Kg_Per_Hour
    , Kg_Per_Hour
    -- Unmodified Kg_Per_Hour times 24 is total in a day possible.
    , Kg_Per_Hour * 24.0 as Total_Possible_KG
    -- Our hours divided by hours in a day
    , ShadowHours / 24.0 * 100 AS Shadow_Percent_of_Total_Hours
    -- the rest
    , Division, Region, Business_Region, Plant, Work_Center, DaysInMonth, Total_Possible_Hours, Demonstrated_Capacity, over_hours
FROM zt_Demonstrated_Capacity_Trend T
    CROSS APPLY (
        SELECT
            ROWID-1 AS ShadowDays
            , CASE WHEN CAST(T.Act_Batch_Time AS NUMERIC(38,15)) - ROWID*24 > 0 THEN 24 ELSE CAST(T.Act_Batch_Time AS NUMERIC(38,15)) % 24.0 END AS ShadowHours
        FROM (
            SELECT ROW_NUMBER()OVER(ORDER BY S.NAME) AS ROWID
            FROM master..spt_values S
            ) X
        WHERE T.Act_Batch_Time - ((ROWID-1)*24) > 0
    ) Z
WHERE T.Act_Batch_Time > 24

DELETE FROM zt_Demonstrated_Capacity_Trend WHERE Act_Batch_Time> 24
COMMIT TRAN

使用交叉應用,並獲得可在其中拆分給定值的人工行,然后使用小時和天數以各種方式放入select語句中,以達到預期的效果。 您希望將其隔離在單個事務中,以防止在insert和delete語句之間進行新插入。 這將比帶有謂詞的光標執行得更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM