Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.server -> Re: Performance issue while loading large amount of data

Re: Performance issue while loading large amount of data

From: Richard Foote <richard.foote_at_bigpond.com>
Date: Wed, 15 Jan 2003 23:29:08 +1000
Message-ID: <RdcV9.24793$jM5.65715@newsfeeds.bigpond.com>


"Howard J. Rogers" <howardjr2000_at_yahoo.com.au> wrote in message news:EzZU9.24111$jM5.64133_at_newsfeeds.bigpond.com...

<big almighty snip>

> Time to start block dumping, I think.

Hi Guys,

OK, kids are in bed, time to do some investigating (and starting by looking at a few block dumps is a good way to go).

As I said somewhere previously, inserts most certainly do generate undo, they must for rollback, read consistency reasons, etc. pretty well as Howard has said. I hopefully will prove that in a minute. The only thing I disagree with what Howard has said/show, to a degree, is what is actually stored in the undo blocks and the amount of undo that actually gets generated. Hopefully I'll also prove that an insert takes somewhere in the order of 70 odd bytes or so and that it is not the rowid that gets stored (as such).

OK, word of warning to everyone, this might be a tad long so if none of this is of interest or block dumps bore you to tears, exit now !! But if you're a newbie to Oracle and you're interested in how people might determine what the hell Oracle does, then hey hang in there, this might useful to you.

Couple of birds with one stone here. Firstly, an insert does generate undo, each and every one of them and the amount of undo is proportional to the number of rows inserted as Howard states. However, the *issue* I have with the examples in this discussion and the reason why it generates so little undo per row is that they all use a subselect. By doing so, Oracle is using an *array insert* mechanism and as such it dramatically reduces the amount of undo that gets generated as multiple rows being inserted into the same block can be recorded very efficiently within the *one* undo record.

Lets take a look at what I mean.

SQL> create table insert_bowie as select * from dba_objects where 1=2;

Table created.

SQL> insert into insert_bowie select * from dba_objects;

30127 rows created.

SQL> select start_ubafil, ubafil, start_ubablk, ubablk, used_ublk, used_urec   2 from v$transaction;

START_UBAFIL UBAFIL START_UBABLK UBABLK USED_UBLK USED_UREC ------------ ---------- ------------ ---------- ---------- ----------

           2 2 1330 1345 15 760

We note that 30127 rows were inserted, using just 15 * 8K blocks and interestingly just 760 undo records. That's no more than 4 bytes of undo per inserted row. How the hell does Oracle use so little undo ?

We'll lets look at one of these undo blocks (in other session) ...

SQL> alter system dump datafile 2 block 1335;

System altered.

I've dumped one of the blocks listed above and this is a small portion of it. Comments with ** is just me trying to explain stuff :)

Start dump data blocks tsn: 1 file#: 2 minblk 1335 maxblk 1335 buffer tsn: 1 rdba: 0x00800537 (2/1335)
scn: 0x0000.016aa6e3 seq: 0x19 flg: 0x04 tail: 0xa6e30219 frmt: 0x02 chkval: 0x9aa2 type: 0x02=KTU UNDO BLOCK



UNDO BLK:
xid: 0x0001.003.000061ce seq: 0x293 cnt: 0x34 irb: 0x34 icl: 0x0 flg: 0x0000

 Rec Offset Rec Offset Rec Offset Rec Offset Rec Offset


0x01 0x1f34     0x02 0x1ea8     0x03 0x1e0c     0x04 0x1d74     0x05 0x1cf8
0x06 0x1c38     0x07 0x1bd0     0x08 0x1af4     0x09 0x1aa4     0x0a 0x19c0
0x0b 0x1978     0x0c 0x1898     0x0d 0x1834     0x0e 0x1770     0x0f 0x16f0
0x10 0x1648     0x11 0x15b0     0x12 0x1524     0x13 0x1470     0x14 0x13fc
0x15 0x1330     0x16 0x12d8     0x17 0x1204     0x18 0x11c8     0x19 0x10f0
0x1a 0x109c     0x1b 0x0fd4     0x1c 0x0f68     0x1d 0x0eb4     0x1e 0x0e2c
0x1f 0x0d8c     0x20 0x0ce8     0x21 0x0c60     0x22 0x0ba0     0x23 0x0b34
0x24 0x0a64     0x25 0x0a14     0x26 0x093c     0x27 0x08f4     0x28 0x0818
0x29 0x07bc     0x2a 0x06f8     0x2b 0x0684     0x2c 0x05d0     0x2d 0x0540
0x2e 0x04ac     0x2f 0x0404     0x30 0x0388     0x31 0x02c8     0x32 0x0264
0x33 0x0184     0x34 0x0138

*-----------------------------

* Rec #0x2 slt: 0x03 objn: 31120(0x00007990) objd: 31120 tblspc: 9(0x00000009)
* Layer: 11 (Row) opc: 1 rci 0x01 Undo type: Regular undo Last buffer split: No Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------

KDO undo record:
KTB Redo
op: 0x03 ver: 0x01
op: Z
KDO Op code: QMD row dependencies Disabled   xtype: XA bdba: 0x0240068d hdba: 0x0240203b itli: 1 ispac: 0 maxfr: 4858
tabn: 0 lock: 0 nrow: 40
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
slot[10]: 10
slot[11]: 11
slot[12]: 12
slot[13]: 13
slot[14]: 14
slot[15]: 15
slot[16]: 16
slot[17]: 17
slot[18]: 18
slot[19]: 19
slot[20]: 20
slot[21]: 21
slot[22]: 22
slot[23]: 23
slot[24]: 24
slot[25]: 25
slot[26]: 26
slot[27]: 27
slot[28]: 28
slot[29]: 29
slot[30]: 30
slot[31]: 31
slot[32]: 32
slot[33]: 33
slot[34]: 34
slot[35]: 35
slot[36]: 36
slot[37]: 37
slot[38]: 38
slot[39]: 39

That's a key point I'm trying to illustrate.

*-----------------------------

* Rec #0x3 slt: 0x03 objn: 31120(0x00007990) objd: 31120 tblspc: 9(0x00000009)

OK, while I've got your attention (if you're not asleep already), I might show you another interesting example. This time let's see what difference an index makes (because it does make more of a difference than some might expect)

Rollback complete.

SQL> create index insert_bowie_idx on insert_bowie(owner);

Index created.

SQL> insert into insert_bowie select * from dba_objects;

30128 rows created.

SQL> select start_ubafil, ubafil, start_ubablk, ubablk, used_ublk, used_urec   2 from v$transaction;

START_UBAFIL UBAFIL START_UBABLK UBABLK USED_UBLK USED_UREC ------------ ---------- ------------ ---------- ---------- ----------

           2 2 445 2883 80 1449

Note that by simply adding one little weeny index which we might suspect will only need roughly double the undo to store has actually generated 433% more undo. Why ? Let's look ...

SQL> alter system dump datafile 2 block 446;

System altered.

*-----------------------------

* Rec #0x1 slt: 0x00 objn: 31121(0x00007991) objd: 31121 tblspc: 9(0x00000009)
* Layer: 10 (Index) opc: 22 rci 0x00 Undo type: Regular undo Last buffer split: No Temp Object: No
Tablespace Undo: No
rdba: 0x008001bd
*-----------------------------

index undo for leaf key operations
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x008001bd.024c.48
Dump kdilk : itl=2, kdxlkflg=0x21 sdc=1 indexid=0x240069b block=0x0240069c purge leaf row
number of keys: 80
key sizes:
 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
key :(880):
 03 53 59 53 06 02 40 20 4a 00 0a 03 53 59 53 06 02 40 20 4a 00 0b 03 53 59  53 06 02 40 20 4a 00 0c 03 53 59 53 06 02 40 20 4a 00 0d 03 53 59 53 06 02  40 20 4a 00 0e 03 53 59 53 06 02 40 20 4a 00 0f 03 53 59 53 06 02 40 20 4a  00 10 03 53 59 53 06 02 40 20 4a 00 11 03 53 59 53 06 02 40 20 4a 00 12 03  53 59 53 06 02 40 20 4a 00 13 03 53 59 53 06 02 40 20 4a 00 14 03 53 59 53  06 02 40 20 4a 00 15 03 53 59 53 06 02 40 20 4a 00 16 03 53 59 53 06 02 40  20 4a 00 17 03 53 59 53 06 02 40 20 4a 00 18 03 53 59 53 06 02 40 20 4a 00  19 03 53 59 53 06 02 40 20 4a 00 1a 03 53 59 53 06 02 40 20 4a 00 1b 03 53  59 53 06 02 40 20 4a 00 1c 03 53 59 53 06 02 40 20 4a 00 1d 03 53 59 53 06  02 40 20 4a 00 1e 03 53 59 53 06 02 40 20 4a 00 1f 03 53 59 53 06 02 40 20  4a 00 20 03 53 59 53 06 02 40 20 4a 00 21 03 53 59 53 06 02 40 20 4a 00 22  03 53 59 53 06 02 40 20 4a 00 23 03 53 59 53 06 02 40 20 4a 00 24 03 53 59  53 06 02 40 20 4a 00 25 03 53 59 53 06 02 40 20 4a 00 26 03 53 59 53 06 02  40 20 4a 00 27 03 53 59 53 06 02 40 20 4a 00 28 03 53 59 53 06 02 40 20 4a  00 29 03 53 59 53 06 02 40 20 4a 00 2a 03 53 59 53 06 02 40 20 4a 00 2b 03  53 59 53 06 02 40 20 4a 00 2c 03 53 59 53 06 02 40 20 4a 00 2d 03 53 59 53  06 02 40 20 4a 00 2e 03 53 59 53 06 02 40 20 4a 00 2f 03 53 59 53 06 02 40  20 4a 00 30 03 53 59 53 06 02 40 20 4a 00 31 03 53 59 53 06 02 40 20 4a 00  32 03 53 59 53 06 02 40 20 4a 00 33 03 53 59 53 06 02 40 20 4a 00 34 03 53  59 53 06 02 40 20 4a 00 35 03 53 59 53 06 02 40 20 4a 00 36 03 53 59 53 06  02 40 20 4a 00 37 03 53 59 53 06 02 40 20 4a 00 38 03 53 59 53 06 02 40 20  4a 00 39 03 53 59 53 06 02 40 20 4a 00 3a 03 53 59 53 06 02 40 20 4a 00 3b  03 53 59 53 06 02 40 20 4a 00 3c 03 53 59 53 06 02 40 20 4a 00 3d 03 53 59  53 06 02 40 20 4a 00 3e 03 53 59 53 06 02 40 20 4a 00 3f 03 53 59 53 06 02  40 20 4a 00 40 03 53 59 53 06 02 40 20 4a 00 41 03 53 59 53 06 02 40 20 4a  00 42 03 53 59 53 06 02 40 20 4a 00 43 03 53 59 53 06 02 40 20 4a 00 44 03  53 59 53 06 02 40 20 4a 00 45 03 53 59 53 06 02 40 20 4b 00 00 03 53 59 53  06 02 40 20 4b 00 01 03 53 59 53 06 02 40 20 4b 00 02 03 53 59 53 06 02 40  20 4b 00 03 03 53 59 53 06 02 40 20 4b 00 04 03 53 59 53 06 02 40 20 4b 00  05 03 53 59 53 06 02 40 20 4b 00 06 03 53 59 53 06 02 40 20 4b 00 07 03 53  59 53 06 02 40 20 4b 00 08 03 53 59 53 06 02 40 20 4b 00 09 03 53 59 53 06  02 40 20 4b 00 0a 03 53 59 53 06 02 40 20 4b 00 0b 03 53 59 53 06 02 40 20  4b 00 0c 03 53 59 53 06 02 40 20 4b 00 0d 03 53 59 53 06 02 40 20 4b 00 0e  03 53 59 53 06 02 40 20 4b 00 0f 03 53 59 53 06 02 40 20 4b 00 10 03 53 59  53 06 02 40 20 4b 00 11 03 53 59 53 06 02 40 20 4b 00 12 03 53 59 53 06 02  40 20 4b 00 13
keydata/bitmap: (10): ff ff ff ff ff ff ff ff ff ff
*-----------------------------

* Rec #0x2 slt: 0x00 objn: 31120(0x00007990) objd: 31120 tblspc: 9(0x00000009)
* Layer: 11 (Row) opc: 1 rci 0x01 Undo type: Regular undo Last buffer split: No Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------

KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x008001bd.024c.4a
KDO Op code: QMD row dependencies Disabled   xtype: XA bdba: 0x0240204b hdba: 0x0240203b itli: 1 ispac: 0 maxfr: 4858
tabn: 0 lock: 0 nrow: 49
slot[0]: 20
slot[1]: 21
slot[2]: 22
slot[3]: 23
slot[4]: 24
slot[5]: 25
slot[6]: 26
slot[7]: 27
slot[8]: 28
slot[9]: 29
slot[10]: 30
slot[11]: 31
slot[12]: 32
slot[13]: 33
slot[14]: 34
slot[15]: 35
slot[16]: 36
slot[17]: 37
slot[18]: 38
slot[19]: 39
slot[20]: 40
slot[21]: 41
slot[22]: 42
slot[23]: 43
slot[24]: 44
slot[25]: 45
slot[26]: 46
slot[27]: 47
slot[28]: 48
slot[29]: 49
slot[30]: 50
slot[31]: 51
slot[32]: 52
slot[33]: 53
slot[34]: 54
slot[35]: 55
slot[36]: 56
slot[37]: 57
slot[38]: 58
slot[39]: 59
slot[40]: 60
slot[41]: 61
slot[42]: 62
slot[43]: 63
slot[44]: 64
slot[45]: 65
slot[46]: 66
slot[47]: 67
slot[48]: 68

I've listed 2 undo records here, one for the index and one for the table. As you can see, there's a fair amount of undo that needs to be recorded for an index. Note also that indexes have branch pages, leaf pages that split etc. and all this needs to be recorded.

Certainly a table that's inserted via an array insert with no indexes generates proportionally much less undo than one that does have an index (or more).

OK, now lets see how thing differ when we don't use an insert array mechanism. Hopefully, we'll see that proportionally the amount of undo that's generated sky rockets.

SQL> rollback;

Rollback complete.

SQL> create table insert_bowie_2 (x number);

Table created.

SQL> insert into insert_bowie_2 values (1);

1 row created.

SQL> / etc...

I now carry on and insert 340 rows into this table.

SQL> select count(*) from insert_bowie_2;

  COUNT(*)


       340

SQL> select start_ubafil, ubafil, start_ubablk, ubablk, used_ublk, used_urec   2 from v$transaction;

START_UBAFIL UBAFIL START_UBABLK UBABLK USED_UBLK USED_UREC ------------ ---------- ------------ ---------- ---------- ----------

           2 2 316 318 3 340

Now this is interesting. With 340 rows, we note that *3* undo blocks are required (assuming the 3rd block is full, that's approximately *70* bytes per row. Also note that the undo record count matches the number of rows *exactly*. I'm not too happy with not knowing the fullness of the last block as it kinda makes the average undo per row too variable for my liking.

So lets keep adding 10 more rows undo we hit 4 undo blocks ...

SQL> insert into insert_bowie_2 values (1);

1 row created.

etc.

SQL> select start_ubafil, ubafil, start_ubablk, ubablk, used_ublk, used_urec   2 from v$transaction;

START_UBAFIL UBAFIL START_UBABLK UBABLK USED_UBLK USED_UREC ------------ ---------- ------------ ---------- ---------- ----------

           2 2 316 319 4 350

Alright !! Now with 350 rows (and corresponding undo records) we now have 3 totally full undo blocks and one almost empty. So we can say that approximately 70 bytes per row is required here for each insert row (the block dump will confirm this is as pretty close to the truth). This is way way way more than the 4 bytes average we originally had !!

The reason should of course be obvious but let's look anyway.

SQL> alter system dump datafile 2 block 317;

System altered.

*-----------------------------

* Rec #0x1 slt: 0x2f objn: 31123(0x00007993) objd: 31123 tblspc: 9(0x00000009)
* Layer: 11 (Row) opc: 1 rci 0x00 Undo type: Regular undo Last buffer split: No Temp Object: No
Tablespace Undo: No
rdba: 0x0080013c
*-----------------------------

KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x0080013c.0213.72
KDO Op code: DRP row dependencies Disabled   xtype: XA bdba: 0x024005b0 hdba: 0x024005ab itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 95(0x5f)
*-----------------------------

* Rec #0x2 slt: 0x2f objn: 31123(0x00007993) objd: 31123 tblspc: 9(0x00000009)
* Layer: 11 (Row) opc: 1 rci 0x01 Undo type: Regular undo Last buffer split: No Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------

KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x0080013d.0213.01
KDO Op code: DRP row dependencies Disabled   xtype: XA bdba: 0x024005b0 hdba: 0x024005ab itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 96(0x60)
*-----------------------------

* Rec #0x3 slt: 0x2f objn: 31123(0x00007993) objd: 31123 tblspc: 9(0x00000009)
* Layer: 11 (Row) opc: 1 rci 0x02 Undo type: Regular undo Last buffer split: No Temp Object: No
Tablespace Undo: No
rdba: 0x00000000
*-----------------------------

KDO undo record:
KTB Redo
op: 0x02 ver: 0x01
op: C uba: 0x0080013d.0213.02
KDO Op code: DRP row dependencies Disabled   xtype: XA bdba: 0x024005b0 hdba: 0x024005ab itli: 1 ispac: 0 maxfr: 4858
tabn: 0 slot: 97(0x61)

I've only listed 3 undo records but as you can see each one corresponds to only the one row as we are not using an array insert in this example. This means that the large undo record header section is duplicated for each and every entry resulting in a vastly increased undo rate per row.

So there we go.

Hopefully this shows that:

  1. Yes undo is generate for each individual row that is inserted (hopefully that settles that debate)
  2. If an insert array is used, then proportionally only a small amount of undo is generated as only the row directory slot info is actually recorded for each row
  3. If a conventional insert is used, then approximately 68 bytes per inserted row is used plus some (which hopefully will explain why sometimes much 'more' undo appears to be generated proportionally for inserts).
  4. Indexes use (proportionally) a lot of undo for inserts.

Sorry if I've bored you all to tears but I hope some of this was useful to you and any newbies out there.

Cheers

Richard Received on Wed Jan 15 2003 - 07:29:08 CST

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US