PLSQL脚本优化/调整
PLSQL script optimisation / tuning
我有这个 plsql 脚本。我能够在大约 300 行的测试 table 上对此进行测试,并且运行良好。但是,当我尝试使用大约 100 万行的实际 table 运行 时,它没有完成。我想征求您关于如何优化我的脚本的建议,我是 plsql 的新手,所以任何 ideas/suggestions 都是很大的帮助。 :)
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;
等效的纯SQL语句:
UPDATE PP_TRANCHE_RBS
SET pt03d = pt04d
WHERE bgroup = 'RBS'
and pt03d = pt04d + 1;
这可能 运行 比您的程序版本快。 PL/SQL 批量处理比逐行处理快,但通常比单个基于集合的操作慢。因此,当您拥有只能通过程序处理的复杂转换逻辑时,请将其保存下来。
我有这个 plsql 脚本。我能够在大约 300 行的测试 table 上对此进行测试,并且运行良好。但是,当我尝试使用大约 100 万行的实际 table 运行 时,它没有完成。我想征求您关于如何优化我的脚本的建议,我是 plsql 的新手,所以任何 ideas/suggestions 都是很大的帮助。 :)
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;
等效的纯SQL语句:
UPDATE PP_TRANCHE_RBS
SET pt03d = pt04d
WHERE bgroup = 'RBS'
and pt03d = pt04d + 1;
这可能 运行 比您的程序版本快。 PL/SQL 批量处理比逐行处理快,但通常比单个基于集合的操作慢。因此,当您拥有只能通过程序处理的复杂转换逻辑时,请将其保存下来。