陌湘萘 2022-02-09 15:31 采纳率: 50%
浏览 24
已结题

SP執行起來太慢,跑一次8個小時左右,如何優化?

後臺數據量比較大,所以撈一次就差不多要7.8個小時左右,如何優化代碼?


ALTER PROCEDURE [dbo].[EMS_GETReferlife]
 @PartNum varchar(20)='4201CUT001210991',
 @BeginDate  varchar(30)='2019/01/01',
 @EndDate varchar(30)='2019/02/15' ,
 --@EType varchar(12)='H-1'
 @EType varchar(12)=''
as

If @BeginDate='12/30/1899'
Begin
set @BeginDate=''
set @EndDate=''
end 

Create Table #EMS_GetReferLife
(
  PartNum varchar(32) null,
  MatName varchar(120) null,
  ReferLife float null,
  UseLife float null
)

Create Table #EMS_GetReferLife_Type
(
  PartNum varchar(32) null,
  MatName varchar(120) null,
  ReferLife float null,
  UseLife float null,
  EquipType varchar(50) null --新增組別
)

Create Table #UseLife
(
  PartNum varchar(32) null,
  UseLife float null,
  EquipType varchar(50) null --新增組別
)

Declare @Cond varchar(300) = ''
--Declare @UseLife_Temp float = 0

IF ISNULL(@PartNum,'') <> ''
Begin
    Select @Cond = @Cond + ' And PartNum = ''' + @PartNum + ''' '
End

Exec(
    'insert into  #EMS_GetReferLife(PartNum,MatName,ReferLife) '+
    'select PartNum,MatName,ReferLife '+
    'from EMS_PartNumBasic(nolock) '+
    'where 1=1 '+ 
    @Cond
    )


declare @PartNumt Varchar(max)
   DECLARE cur CURSOR FOR  
        Select PartNum From #EMS_GetReferLife(NoLock)             
    OPEN cur
    FETCH NEXT FROM cur INTO @PartNumt
    WHILE @@FETCH_STATUS = 0
    BEGIN
        insert into #UseLife(PartNum,UseLife,EquipType)
        select t1.partnum,t1.uselife,t2.EquipType
        from dbo.EMS_RequestPart t1(nolock) ,dbo.EMS_RequestMas t2(nolock) 
         where  t2.papernum = t1.PaperNum
         and  t1.PartNum =@PartNumt
         and ((paperdate>@BeginDate) or (@BeginDate=''))
         and ((paperdate<@EndDate) or (@EndDate=''))
         and ((t2.Equiptype=@EType) or (@EType=''))

        insert into #UseLife(PartNum,UseLife,EquipType)
        select t1.PartNum,t1.uselife,t2.EquipType
        from dbo.EMS_RequestPart_main t1(nolock) ,dbo.EMS_maintainnoticeMas t2(nolock) 
        where  t2.papernum = t1.PaperNum
        and  t1.PartNum =@PartNumt
        and paperdate>@BeginDate
        and paperdate<@EndDate
        and ((t2.Equiptype=@EType) or (@EType=''))

        --計算平均值之前先按組別分類彙總

         select PartNum,EquipType,avg(uselife) as UseLife_Temp
         into #UseLife_Temp
         from #UseLife(nolock)
         group by PartNum,equipType

         --select * from #UseLife_Temp(nolock)

            declare @EquipType Varchar(max)
            DECLARE @UseLife_Type varchar(max)
            DECLARE curType CURSOR FOR  
                Select EquipType,UseLife_Temp From #UseLife_Temp(NoLock)             
            OPEN curType
            FETCH NEXT FROM curType INTO @EquipType,@uselife_Type
            WHILE @@FETCH_STATUS = 0
            BEGIN
                 

                 insert into #EMS_GetReferLife_Type(PartNum,MatName,ReferLife,EquipType)
                 SELECT PartNum,MatName,ReferLife,@EquipType
                 from #EMS_GetReferLife t1(nolock)
                 where t1.PartNum=@PartNumt

                 update t1
                 set t1.UseLife=@Uselife_Type
                 from #EMS_GetReferLife_Type t1(nolock)
                 where t1.PartNum=@PartNumt
                 and t1.EquipType=@EquipType

                  FETCH NEXT FROM curType 
              INTO  @EquipType,@uselife_Type
            END
            CLOSE curType
            DEALLOCATE curType


         delete from #UseLife
         drop table #UseLife_Temp

      FETCH NEXT FROM cur 
      INTO  @PartNumt
    END
    CLOSE cur
    DEALLOCATE cur
    


     select  PartNum as 物料編碼,MatName as 物料名稱,ReferLife as 參考日期,UseLife as 使用日期 ,EquipType as 組別
     from  #EMS_GetReferLife_Type(nolock)

truncate table #EMS_GetReferLife
truncate table #EMS_GetReferLife_Type
truncate table #UseLife

有想過用View取代臨時表,但速度上并沒有優化。

  • 写回答

1条回答 默认 最新

  • IT阿沈 2022-02-09 16:27
    关注

    我給一個思路,你看一下是否可以緩解你的問題:

    -- 就拿以下代碼來說
    DECLARE cur CURSOR FOR   -- 這個位置的遊標我覺得必要性不大,如果返回值較多的話,太影響效率了
            Select PartNum From #EMS_GetReferLife(NoLock)      -- 可以將這個語句作為下面insert 語句中的條件       
        OPEN cur
        FETCH NEXT FROM cur INTO @PartNumt
        WHILE @@FETCH_STATUS = 0
        BEGIN
          -- 先註釋掉 
         --   insert into #UseLife(PartNum,UseLife,EquipType)
         --   select t1.partnum,t1.uselife,t2.EquipType
         --   from dbo.EMS_RequestPart t1(nolock) ,dbo.EMS_RequestMas t2(nolock) 
         --    where  t2.papernum = t1.PaperNum
         --    and  t1.PartNum =@PartNumt
         --    and ((paperdate>@BeginDate) or (@BeginDate=''))
         --    and ((paperdate<@EndDate) or (@EndDate=''))
         --    and ((t2.Equiptype=@EType) or (@EType=''))
    
    --  改為:
            insert into #UseLife(PartNum,UseLife,EquipType)
            select t1.partnum,t1.uselife,t2.EquipType
            from dbo.EMS_RequestPart t1(nolock) ,dbo.EMS_RequestMas t2(nolock) 
             where   t2.papernum = t1.PaperNum
             and  exists(Select  1 From #EMS_GetReferLife(NoLock) t3 where t3.PartNum = t1.PartNum ) -- 取代  t1.PartNum =@PartNumt
             and ((paperdate>@BeginDate) or (@BeginDate=''))
             and ((paperdate<@EndDate) or (@EndDate=''))
             and ((t2.Equiptype=@EType) or (@EType=''))
    
    -- 下同:
            insert into #UseLife(PartNum,UseLife,EquipType)
            select t1.PartNum,t1.uselife,t2.EquipType
            from dbo.EMS_RequestPart_main t1(nolock) ,dbo.EMS_maintainnoticeMas t2(nolock) 
            where  t2.papernum = t1.PaperNum
            and exists(Select  1 From #EMS_GetReferLife(NoLock) t3 where t3.PartNum = t1.PartNum ) -- 取代  t1.PartNum =@PartNumt 
            and paperdate>@BeginDate
            and paperdate<@EndDate
            and ((t2.Equiptype=@EType) or (@EType=''))
    

    現在的情況是一個遊標又套了一層遊標,insert和update的次數無法控制,效率難以保證,將能夠避免的遊標全部去掉,然後儘量使用“批處理”,應該是可以提升不少執行效率的。

    希望可以幫助到你。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 系统已结题 5月28日
  • 已采纳回答 5月20日
  • 创建了问题 2月9日

悬赏问题

  • ¥15 企业资源规划ERP沙盘模拟
  • ¥15 前端echarts坐标轴问题
  • ¥15 CMFCPropertyPage
  • ¥15 ad5933的I2C
  • ¥15 请问RTX4060的笔记本电脑可以训练yolov5模型吗?
  • ¥15 数学建模求思路及代码
  • ¥50 silvaco GaN HEMT有栅极场板的击穿电压仿真问题
  • ¥15 谁会P4语言啊,我想请教一下
  • ¥15 这个怎么改成直流激励源给加热电阻提供5a电流呀
  • ¥50 求解vmware的网络模式问题 别拿AI回答