【问题标题】:Sybase stored procedure taking too longSybase 存储过程耗时过长
【发布时间】:2015-12-31 16:57:05
【问题描述】:

以下存储过程正在运行 4 小时。无论如何我可以优化它以将执行时间缩短到 10 分钟以下?

表 #TbTemp 有 150k 行。并且光标循环了 15 万次。

由于我正在处理临时表,因此我将完全控制创建任何索引等。

既然应该避免使用游标,有什么替代解决方案吗?

declare tmpCur cursor
for
select LnNo,instDrftCreatnDt
from   #TbTemp
for read only

open tmpCur

while (1 = 1)
begin   --{
    fetch tmpCur into @LnNo,@Dt

    insert into #TmpLnPmt
            (RecTyp,InstNo,LnNo,TotCurChrgdFactr,PmtTyp,
            CurrChrgdFactr,CurrPmtAmt,PrevCmptdPmtAmt,NetCmptdPmtAmt)
    select  '01', @InstNo, @LnNo, @TotCurChrgdFactr, pc.PmtTyp,
            0, 0, pc.cmptdPmtAmt, 0-pc.cmptdPmtAmt
    from    Ln l, Pmt pt, PmtCmpnt pc
    where   l.LnNo = @LnNo
    and     pt.mbsLoanPID = l.identifier
    and     pt.instDrftCreatnDt = @Dt
    and     pc.paymentComponentsPaymentPID = pt.identifier
    and     pc.PmtTyp not in (select   PmtTyp
                    from    #TbTemp
                    where   LnNo = @LnNo)
    and     not exists (select  1 from #TmpLnPmt
                where   LnNo = @LnNo
                and     PmtTyp = pc.PmtTyp)
    end --}
close tmpCur
deallocate cursor tmpCur                            

【问题讨论】:

  • 澄清一下,应该避免的不仅仅是游标,还有任何循环或逐行迭代。 RDBMS 基于集合的概念,并针对集合而非行进行了优化。

标签: sql stored-procedures cursor sybase sql-optimization


【解决方案1】:

这是不使用CURSOR的一种方法

INSERT INTO #tmplnpmt 
            (rectyp, 
             instno, 
             lnno, 
             totcurchrgdfactr, 
             pmttyp, 
             currchrgdfactr, 
             currpmtamt, 
             prevcmptdpmtamt, 
             netcmptdpmtamt) 
SELECT '01', 
       @InstNo, 
       a.lnno, 
       @TotCurChrgdFactr, 
       pc.pmttyp, 
       0, 
       0, 
       pc.cmptdpmtamt, 
       0 - pc.cmptdpmtamt 
FROM   ln l 
       INNER JOIN pmt pt 
               ON pt.mbsloanpid = l.identifier 
       INNER JOIN pmtcmpnt pc 
               ON pc.paymentcomponentspaymentpid = pt.identifier 
       INNER JOIN #tbtemp a 
               ON l.lnno = a.lnno 
                  AND pt.instdrftcreatndt = a.instdrftcreatndt 
WHERE  NOT EXISTS (SELECT pmttyp 
                   FROM   #tbtemp t 
                   WHERE  t.pmttyp = pc.pmttyp) 
       AND NOT EXISTS (SELECT 1 
                       FROM   #tmplnpmt a 
                              INNER JOIN #tbtemp b 
                                      ON a.lnno = b.lnno 
                                         AND pmttyp = pc.pmttyp) 

【讨论】:

  • 抱歉,复制时出现拼写错误。 #instpmtcmpnt 在原始问题中也应该是 #tbtemp。你能再检查一下吗?感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-09
  • 2013-11-16
  • 1970-01-01
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多