在循环中进行提交的测试

    Oracle版本中,如果commit,那么后台的LGWR进程一定会将内存中的redo数据写入
online redo log文件中,然后再将控制权返回给用户(当然,其实这段也可能不是磁
盘操作,而是写入到磁盘缓冲中)。如果应用中有过于频繁的用户commit,那么可能
会产生明显的log file sync的等待事件。

在loop中提交可能带来的问题:
    性能降低
    当undo比较小的时候,可能出现ora-01555(单次可能发生ora-30036)
    如果失败,数据不一致(一些修改commit了,一些没有)   


DROP TABLE t PURGE;
DROP TABLE t1 PURGE;
CREATE TABLE t AS SELECT * FROM all_objects;
CREATE TABLE t1 (i int,x NUMBER);
--BEGIN dbms_stats.gather_table_stats(USER,'T');END;

SELECT i, count(i),AVG(x) FROM t1 GROUP BY i ORDER BY 3;

-----------------------------------------------------
DECLARE
v_cnt1 NUMBER;
v_cnt2 NUMBER;
v_cnt3 NUMBER;
TYPE ridarr IS TABLE OF ROWID;
TYPE narr IS TABLE OF t.object_name%TYPE;
CURSOR c IS
SELECT ROWID rid, object_name FROM t;
lrid ridarr;
lname narr;
BEGIN
v_cnt1 := dbms_utility.get_time;
UPDATE t SET t.object_name = lower(t.object_name);
COMMIT;
v_cnt2 := dbms_utility.get_time;
INSERT INTO t1(i, x) VALUES(1,v_cnt2-v_cnt1);
COMMIT;

v_cnt3 := 0;
v_cnt1 := dbms_utility.get_time;
FOR x IN (SELECT ROWID rid, object_name oname FROM t) LOOP
UPDATE t SET t.object_name = lower(x.oname) WHERE t.ROWID = x.rid;
v_cnt3 := v_cnt3 + 1;
IF v_cnt3 >= 100 THEN
COMMIT;
v_cnt3 := 0;
END IF;
END LOOP;
v_cnt2 := dbms_utility.get_time;
INSERT INTO t1(i, x) VALUES(2,v_cnt2-v_cnt1);
COMMIT;

v_cnt1 := dbms_utility.get_time;
FOR x IN (SELECT ROWID rid, object_name oname, ROWNUM rn FROM t) LOOP
UPDATE t SET t.object_name = lower(x.oname) WHERE t.ROWID = x.rid;
IF MOD(x.rn, 100) = 0 THEN
COMMIT;
END IF;
END LOOP;
v_cnt2 := dbms_utility.get_time;
INSERT INTO t1(i, x) VALUES(3,v_cnt2-v_cnt1);
COMMIT;

v_cnt1 := dbms_utility.get_time;
OPEN c;
LOOP
FETCH c BULK COLLECT
INTO lrid, lname LIMIT 100;
FORALL i IN 1 .. lrid.COUNT
UPDATE t SET t.object_name = lname(i) WHERE ROWID = lrid(i);
COMMIT;
EXIT WHEN c%NOTFOUND;
END LOOP;
CLOSE c;
v_cnt2 := dbms_utility.get_time;
INSERT INTO t1(i, x) VALUES(4,v_cnt2-v_cnt1);
COMMIT;

END;
/



原文地址:https://www.cnblogs.com/wait4friend/p/2345510.html