Using bulk binds for fewer redo records
October 20, 2010 Leave a comment
Redo logs are made of redo records; each redo record is composed by redo change vectors, each of which describes a DB block level change.
Insert with bulk binds, aka bulk insert, can boost your program’s performance by processing many rows from a cursor in one call instead of one row at a time. It also generates fewer redo change vectors therefore less amount of redo logs records.
create table t1 (
a number,
b varchar2(10)
);
[Case 1] Insert one row at a time.
DECLARE
v_Counter BINARY_INTEGER := 1;
BEGIN
WHILE v_Counter <= 10 LOOP
INSERT INTO t1 (a, b) VALUES (v_Counter, v_counter);
v_Counter := v_Counter + 1;
END LOOP;
END;
/
commit;
I dump the redo logs about the changes, after finding redo log name and DBA information.
ALTER SYSTEM DUMP LOGFILE '/…/redolog-1554-1-1232324.arc' DBA MIN 1 39898 DBA MAX 1 39898;
What I see is 10 redo change records. 1 redo record per insert. I paste 1 of 10 here.
REDO RECORD – Thread:1 RBA: 0×000612.0000014d.0140 LEN: 0x016c VLD: 0×01
…
CHANGE #1 TYP:0 CLS:19 AFN:2 DBA:0×00800099 OBJ:4294967295 SCN:0×0000.00d3ccef SEQ: 1 OP:5.2 ENC:0
…
CHANGE #2 TYP:0 CLS:20 AFN:2 DBA:0x0081b92d OBJ:4294967295 SCN:0×0000.00d3ccee SEQ: 3 OP:5.1 ENC:0
…
Tablespace Undo: No
0×00000000 prev ctl uba: 0x0081b92d.03bb.07
..
CHANGE #3 TYP:0 CLS: 1 AFN:1 DBA:0x00409bda OBJ:21674 SCN:0×0000.00d3cd01 SEQ: 3 OP:11.2 ENC:0
KTB Redo
…
null: –
col 0: [ 2] c1 02
col 1: [ 1] 31
[Case 2] Bulk insert with 10 rows at a time. To get an individual redo log, I switch logfile first.
declare
type testnumberarray is table of number index by binary_integer;
type testchararray is table of varchar2(10) index by binary_integer;
v_a testnumberarray;
v_b testchararray;
cursor cu_cursor is select a,b from t1_copy; — (t1_copy has 10 records.)
begin
open cu_cursor;
loop
fetch cu_cursor bulk collect into v_a, v_b LIMIT 10;
forall i in 1 .. v_a.count
insert into t1
values
( v_a(i), v_b(i) );
exit when cu_cursor%notfound;
end loop;
close cu_cursor;
end;
/
Then I dump the new redo log for the change to blocks.
REDO RECORD – Thread:1 RBA: 0x00061b.00000043.0140 LEN: 0x01dc VLD: 0×01
…
CHANGE #1 TYP:0 CLS:23 AFN:2 DBA:0x008000b9 OBJ:4294967295 SCN:0×0000.00d41e1a SEQ: 1 OP:5.2 ENC:0
…
CHANGE #2 TYP:0 CLS:24 AFN:2 DBA:0x0080c891 OBJ:4294967295 SCN:0×0000.00d41e19 SEQ: 1 OP:5.1 ENC:0
…
KTB Redo
…
tabn: 0 lock: 0 nrow: 10
slot[0]: 0
slot[1]: 1
slot[2]: 2
slot[3]: 3
slot[4]: 4
slot[5]: 5
slot[6]: 6
slot[7]: 7
slot[8]: 8
slot[9]: 9
CHANGE #3 TYP:0 CLS: 1 AFN:1 DBA:0x00409bda OBJ:21691 SCN:0×0000.00d41e38 SEQ: 3 OP:11.11 ENC:0
KTB Redo
…
tabn: 0 lock: 1 nrow: 10
slot[0]: 0
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 02
col 1: [ 1] 31
slot[1]: 1
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 03
col 1: [ 1] 32
slot[2]: 2
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 04
col 1: [ 1] 33
slot[3]: 3
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 05
col 1: [ 1] 34
slot[4]: 4
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 06
col 1: [ 1] 35
slot[5]: 5
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 07
col 1: [ 1] 36
slot[6]: 6
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 08
col 1: [ 1] 37
slot[7]: 7
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 09
col 1: [ 1] 38
slot[8]: 8
tl: 8 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 0a
col 1: [ 1] 39
slot[9]: 9
tl: 9 fb: –H-FL– lb: 0×0 cc: 2
col 0: [ 2] c1 0b
col 1: [ 2] 31 30
END OF REDO DUMP
With bulk binds, Oracle generates 1 redo change records for all 10 rows, since only 1 insert sql is fired. As an result, given the same data to insert, with bulk binds generates much less amount of redo logs.