ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 一次对批处理程序的优化

一次对批处理程序的优化

原创 Linux操作系统 作者:lsq_008 时间:2008-10-10 20:13:48 0 删除 编辑

针对日终时间较长的问题,做了一下分析,以下是从日终时间段的statspack报告中获取的信息:
                                                     CPU      Elapsd
  Buffer Gets    Executions  Gets per Exec  %Total Time (s)  Time (s) Hash Value
--------------- ------------ -------------- ------ -------- --------- ----------
    142,148,687            1  142,148,687.0   11.1  1986.08   6166.47 3208775729
Module: stat_bonus@ECTIP (TNS V1-V3)
call CCB_STAT_CUSBONUS(to_date(:b0,'YYYYMMDD')) into :b1

    141,236,813            1  141,236,813.0   11.1  2175.60   5926.47 2278049678
Module: stat_BcLog@ECTIP (TNS V1-V3)
call CCB_CTOH_BC_LOG(to_date(:b0,'YYYYMMDD')) into :b1

    100,595,351            1  100,595,351.0    7.9  1496.40   1543.58 1889229293
Module: stat_bonus@ECTIP (TNS V1-V3)
UPDATE BC_CUSBONUS A SET A.MODI_DATE = :B1 , A.BONUS = ( A.BONUS
 + NVL ((SELECT SUM (NVL (B.AWARD, 0) * DECODE (B.FLAG,'0', 1,'1
',-1,0)) FROM BM_LOG_AWARD B WHERE A.USERID = B.USERID AND A.BRA
NCH_CODE = B.BRANCH_CODE AND B.STATUS = '1' AND B.TRAN_DATE >= :
B1 AND B.TRAN_DATE < :B2 GROUP BY B.USERID, B.BRANCH_CODE), 0 )

     34,733,395    2,378,691           14.6    2.7   738.46   2185.12 1487635544
Module: stat_BcLog@ECTIP (TNS V1-V3)
INSERT INTO BC_LOG_HIS (CREDIT_NO,PTXCODE,LOG_CODE,TXCODE,TRAN_D
ATE,BRANCH_CODE,USERID, IP_ADD,LOG_STR,ERR_CODE,ERR_MSG,STATUS,D
AC,OID,TRAN_MONTH) VALUES ( :B15 ,:B14 ,:B13 ,:B12 ,:B11 ,:B10 ,
:B9 , :B8 ,:B7 ,:B6 ,:B5 ,:B4 ,:B3 ,:B2 ,:B1 )

其中INSERT INTO BC_LOG_HIS。。。这条sql执行了2,378,691次,耗时2185.12秒,查看耗时最长的2个函数,发现这条sql是在函数CCB_CTOH_BC_LOG里执行的,
这个函数的功能是将bc_log表里的数据插入到bc_log_his中,并删除bc_log中的记录,在该函数内容如下:
CREATE OR REPLACE FUNCTION "CCB_CTOH_BC_LOG" (statDate DATE) RETURN NUMBER IS
/*
** BC_LOG倒数到BC_LOG_HIS分段提交
*/

nNum              NUMBER;
nCommitNum        CONSTANT NUMBER :=100000 ;

v_error_code      NUMBER;       --error code
v_error_message   VARCHAR2(255);--error message
v_next_day                date;
v_halfmonth_day   date;
v_seven_day       date;

------------------------------------------------------------------
v_CREDIT_NO     BC_LOG.CREDIT_NO%TYPE;
v_PTXCODE       BC_LOG.PTXCODE%TYPE;
v_LOG_CODE      BC_LOG.LOG_CODE%TYPE;
v_TXCODE        BC_LOG.TXCODE%TYPE;
v_TRAN_DATE     BC_LOG.TRAN_DATE%TYPE;
v_BRANCH_CODE   BC_LOG.BRANCH_CODE%TYPE;
v_USERID        BC_LOG.USERID%TYPE;
v_IP_ADD        BC_LOG.IP_ADD%TYPE;
v_LOG_STR       BC_LOG.LOG_STR%TYPE;
v_ERR_CODE      BC_LOG.ERR_CODE%TYPE;
v_ERR_MSG       BC_LOG.ERR_MSG%TYPE;
v_STATUS        BC_LOG.STATUS%TYPE;
v_DAC           BC_LOG.DAC%TYPE;
v_OID           BC_LOG.OID%TYPE;

v_TRAN_MONTH    NUMBER;
------------------------------------------------------------------

CURSOR ccb_trans_C IS                                                                              -- b2c cursor
        SELECT
        CREDIT_NO,PTXCODE,LOG_CODE,TXCODE,TRAN_DATE,BRANCH_CODE,USERID,
        IP_ADD,LOG_STR,ERR_CODE,ERR_MSG,STATUS,DAC,OID,to_char(tran_date,'mm')
        FROM BC_LOG
        WHERE tran_date        FOR UPDATE WAIT 300;

------------------------------------------------------------------

------------------------------------------------------------------
BEGIN

  LOOP
  --
    nNum := 0;

        OPEN ccb_trans_C;
        LOOP

    FETCH ccb_trans_C INTO
                v_CREDIT_NO,v_PTXCODE,v_LOG_CODE,v_TXCODE,v_TRAN_DATE,v_BRANCH_CODE,v_USERID,
                v_IP_ADD,v_LOG_STR,v_ERR_CODE,v_ERR_MSG,v_STATUS,v_DAC,v_OID,v_TRAN_MONTH;

                EXIT WHEN ccb_trans_C%NOTFOUND;

                INSERT INTO BC_LOG_HIS
                (CREDIT_NO,PTXCODE,LOG_CODE,TXCODE,TRAN_DATE,BRANCH_CODE,USERID,
                IP_ADD,LOG_STR,ERR_CODE,ERR_MSG,STATUS,DAC,OID,TRAN_MONTH)
                VALUES
                (
                v_CREDIT_NO,v_PTXCODE,v_LOG_CODE,v_TXCODE,v_TRAN_DATE,v_BRANCH_CODE,v_USERID,
                v_IP_ADD,v_LOG_STR,v_ERR_CODE,v_ERR_MSG,v_STATUS,v_DAC,v_OID,v_TRAN_MONTH
                );

                DELETE FROM BC_LOG WHERE CURRENT OF ccb_trans_C ;

                nNum := nNum + 1;

        END LOOP;
        CLOSE ccb_trans_C;
        COMMIT;

        EXIT WHEN nNum=0 OR nNum< nCommitNum - 1;
  --
  END LOOP;

COMMIT;
RETURN (1);

EXCEPTION
  WHEN OTHERS THEN
   v_error_code := SQLCODE ;
   v_error_message := SQLERRM ;
   ROLLBACK;

   if ccb_trans_C%isopen then
        close ccb_trans_C;
   end if;

   INSERT INTO BM_PROC_ERR(func_name,err_stat,err_time,err_table,err_msg,err_code) VALUES ('CCB_CTOH_BC_LOG',' ',SYSDATE,'BC_LOG_HIS',v_error_message,v_error_code) ;
   COMMIT;
   RETURN (0);
END CCB_CTOH_BC_LOG;

可以看出,执行insert和delete的操作时,是采用循环的方式逐条实现,并批量提交。这相当于对于每条符合条件的记录,执行一次insert和delete操作,这种方式的效率比较低下。
测试如下:


SQL> insert into test1 select * from bc_log_bak where rownum<10000;
 
9999 rows created.
 
SQL> commit;
 
Commit complete.
 
SQL> insert into test2 select * from bc_log_bak where rownum<10000;
 
9999 rows created.
 
SQL> commit;
 
Commit complete.
 
SQL> set timing on
SQL> delete from test1 ;
 
9999 rows deleted.
 
Elapsed: 00:00:00.43
SQL> commit;
 
Commit complete.
 
Elapsed: 00:00:00.01
SQL> begin
  2  for i in 1 .. 10000 loop
  3  delete from test2 where rownum<2;
  4  end loop;
  5  end;
  6  /
 
PL/SQL procedure successfully completed.
 
Elapsed: 00:00:03.75

可见,采用逐条删除的方式消耗的时间明显长于一次性删除。

如果开发人员能优化一下日终处理程序,那么耗时会有效的降低。

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10972173/viewspace-469950/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: Transaction Naming
请登录后发表评论 登录
全部评论
十余年大型金融及电信系统数据库管理经验,曾服务于中国建设银行、中国移动。对oracle,mysql数据库有深入了解。 擅长python开发,独立开发了开源数据库自动化监控运维平台Power Monitor。

注册时间:2008-02-29

  • 博文量
    335
  • 访问量
    1369151