0

我有这个 plsql 脚本。我能够在大约 300 行的测试表上对其进行测试,并且运行良好。但是,当我尝试使用大约 1M 行的实际表运行它时,它没有完成。我想就如何优化我的脚本征求你的建议,我是 plsql 的新手,所以任何想法/建议都会有很大帮助。:)

DECLARE
    c_BGROUP    PP_TRANCHE_RBS.BGROUP%TYPE := 'RBS';
    l_start     NUMBER;

    /* Check for all entries where pt03d = pt04d+1. */
    CURSOR c_pp_tranche IS
        SELECT 
            refno,
            pt04d,
            seqno
        FROM PP_TRANCHE_RBS a
        WHERE a.BGROUP = c_BGROUP
        AND a.pt03d = (SELECT (pt04d + 1) 
                       FROM PP_TRANCHE_RBS 
                       WHERE bgroup = a.bgroup 
                       AND refno = a.refno 
                       and seqno = a.seqno)
    ;

    TYPE c_refno IS TABLE OF PP_TRANCHE_RBS.REFNO%TYPE;
    TYPE c_pt04d IS TABLE OF PP_TRANCHE_RBS.PT04D%TYPE;
    TYPE c_seqno IS TABLE OF PP_TRANCHE_RBS.SEQNO%TYPE;

    t_refno c_refno;
    t_pt04d c_pt04d;
    t_seqno c_seqno;

BEGIN

    DBMS_OUTPUT.put_line('Updating rows... ');

    l_start := DBMS_UTILITY.get_time;

    OPEN c_pp_tranche;
    LOOP

        FETCH c_pp_tranche BULK COLLECT INTO t_refno, t_pt04d, t_seqno LIMIT 10000; -- break the data into chucks of 10000 rows
        EXIT WHEN t_refno.COUNT() = 0; -- cursor attribute to exit when 0.

        FORALL i IN t_refno.FIRST .. t_refno.LAST

            /* Update pt03d = pt04d */
            UPDATE PP_TRANCHE_RBS
            SET pt03d = t_pt04d(i)
            WHERE
                bgroup = c_BGROUP
                AND refno = t_refno(i)
                AND seqno = t_seqno(i)
            ;   

        -- Process contents of collection here.
        DBMS_OUTPUT.put_line(t_refno.count || ' rows was updated');     

    END LOOP;

        DBMS_OUTPUT.put_line('Bulk Updates Time: ' || (DBMS_UTILITY.get_time - l_start));

    CLOSE c_pp_tranche;
END;
/

exit;
4

1 回答 1

4

等价的纯SQL语句:

  UPDATE PP_TRANCHE_RBS
  SET pt03d = pt04d
  WHERE bgroup = 'RBS'
  and   pt03d = pt04d + 1;

这可能会比您的程序版本运行得更快。PL/SQL 批量处理比逐行处理要快,但通常比单个基于集合的操作要慢。因此,当您具有只能通过程序处理的复杂转换逻辑时,请将其保存。

于 2017-06-14T16:46:07.613 回答