WHAT HAPPENS TO INDEX ENTRY WHEN WE DELETE/UPDATE CORRESPONDING ROW FROM TABLE ??
create a table and index:
SQL> create
table test_table (id number, name varchar2(20));
Table created.
SQL> insert into
test_table values (1, 'JUNK1');
1 row created.
SQL> insert into
test_table values (2, 'JUNK2');
1 row created.
SQL> commit;
Commit complete.
SQL> create
index test_table_idx on test_table (id);
Index created.
SQL> select
object_id from dba_objects where
object_name='TEST_TABLE_IDX';
OBJECT_ID
----------
73515
Now dump the Index structure:
SQL> alter
session set events
'immediate trace name treedump level
73515';
Session altered.
----- begin tree dump
leaf: 0x10007d3 16779219 (0: nrow: 2 rrow: 2)
----- end tree dump
nrow: number of all index entries including deleted
entries
rrows: number of
current index entries
DBA: 16779219 (DATA BLOCK ADDRESS)
OBSERVATION: there
is only one leafblock/root block which has two row entries.(no deleted entries as nrow = rrow)
Dump the leafblock:
We have only one leafblock which is also a root block, and
rootblock is allways next to header block.
SQL> select
header_file, header_block from dba_segments where
segment_name='TEST_TABLE_IDX';
HEADER_FILE HEADER_BLOCK
-----------
------------
4 2002
So root block# = 2002+1
or we can find the block address using DBA (Which we got from treedump)
SQL> select
DBMS_UTILITY.DATA_BLOCK_ADDRESS_FILE(16779219),
DBMS_UTILITY.DATA_BLOCK_ADDRESS_BLOCK(16779219)
from dual;
File # Block#
----------------------------------------------- 4 2003
Sql> alter
system dump datafile 4 block 2003;
Session altered
Leaf block dump
===============
header address
3086706276=0xb7fb6664
kdxcolev 0
KDXCOLEV Flags = -
- -
kdxcolok 0
kdxcoopc 0x80:
opcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 2
kdxcofbo 40=0x28
kdxcofeo
8008=0x1f48
kdxcoavs 7968
kdxlespl 0
kdxlende 0
kdxlenxt 0=0x0
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8032
row#0[8020] flag:
------, lock: 0, len=12
col 0; len 2;
(2): c1 02 à value of
indexed column
col 1; len 6;
(6): 01 00 07 cd 00 00
à rowid
appended
row#1[8008] flag:
------, lock: 0, len=12
col 0; len 2;
(2): c1 03 à value of
indexes column
col 1; len 6;
(6): 01 00 07 cd 00 01
à rowid
appended
-----
end of leaf block dump -----
End
dump data blocks tsn: 4 file#: 4 minblk 2003 maxblk 2003
Now Delete one row
from table:
OBSERVATION: leaf block contains the two rows entries (one for each row in table).
DELETE A ROW FROM TABLE:
Sql>
delete from test_table where id=1;
1
row deleted
Sql>
commit;
Commited
SQL> alter session set events
'immediate trace name treedump level 73515';
Session
altered.
----- begin tree dump
leaf: 0x10007d3
16779219 (0: nrow: 2
rrow: 1)
----- end tree dump
Dumpfile
indicates that we have only one current entry (rrow=1)
And
total rows including marked as delete = 2 (nrow=2)
--Index has two rows entries even after we deleted a row from the table. i.e corresponding index is just marked as DELETE but not deleted physically.
Lets dump the leafblock:
SQL> alter
system dump datafile 4 block 2003;
System
altered
Leaf block dump
===============
header address
3086706276=0xb7fb6664
…………………………………………………………………………………………….
row#0[8020] flag: ---D--, lock: 2, len=12
col 0; len 2;
(2): c1 02
col 1; len 6;
(6): 01 00 07 cd 00 00 à deleted rowid
row#1[8008] flag: ------, lock: 0, len=12
col 0; len 2;
(2): c1 03
col 1; len 6;
(6): 01 00 07 cd 00 01
à current
existing rowid
----- end of leaf
block dump -----
End
dump data blocks tsn: 4 file#: 4 minblk 2003 maxblk 2003
Observations:
First
row entry is still there but marked as DELETE with flag “D”
Now
lets see what if inserted a new row into the table:
SQL> insert into
test_table values (3, 'JUNK2');
1 row created.
SQL> commit;
Commit complete.
SQL> alter
system dump datafile 4 block 2003;
System
altered
Leaf block dump
===============
header address
3086706276=0xb7fb6664
…………………………………………………………………………………………….
row#0[8008] flag: ------, lock: 0, len=12
col 0; len 2;
(2): c1 03
col 1; len 6;
(6): 01 00 07 cd 00 01
àold
remaining rowid
row#1[7996] flag: ------, lock: 2, len=12
col 0; len 2;
(2): c1 04
col 1; len 6;
(6): 01 00 07 cd 00 02 à New rowid
----- end of leaf
block dump -----
End dump data
blocks tsn: 4 file#: 4 minblk 2003 maxblk 2003
Observation:
As soon as a new rowentry added to
the leaf block the row entry which was marked as ‘DELETE’ was actually deleted
from the leafblock.
So row entries that are marked as DELETE will be physically deleted when new row is inserted into the leaf block.
This behaviour is confirmed also by
dumping the tree structure:
----- begin tree dump
leaf: 0x10007d3
16779219 (0: nrow: 2
rrow: 2) à no more deleted entry
----- end tree dump
What Happenes when the row
updated ??
Now we know that if rows are deleted then corresponding index row
entries are marked as DELETE initially and if any new row entries are inserted
into the leaf blocks then it actually delets the row entries that are marked as DELETTE
previosly.
But what happens to the index row entries when corresponding rows
are updated ??
SQL>
select * from test_table;
ID NAME
---------- --------------------
2
JUNK
3 JUNK2
SQL> alter system dump datafile 4 block 2003;
Leaf block dump
===============
header address
3086706276=0xb7fb6664
…………………………………………………………………………………………….
row#0[8008] flag: ------, lock: 0, len=12
col 0; len 2;
(2): c1 03
col 1; len 6;
(6): 01 00 07 cd 00 01
row#1[7996] flag: ------, lock: 2, len=12
col 0; len 2;
(2): c1 04
col 1; len 6;
(6): 01 00 07 cd 00 02
----- end of leaf
block dump -----
End dump data
blocks tsn: 4 file#: 4 minblk 2003 maxblk 2003
Now
update the row:
SQL>
update test_table set id=4 where name='JUNK2';
1 row updated.
SQL>
commit;
Commit complete.
Leaf block dump
===============
header address
3086706276=0xb7fb6664
…………………………………………………………………………………………….
row#0[8008] flag: ------, lock: 0, len=12
col 0; len 2;
(2): c1 03
col 1; len 6;
(6): 01 00 07 cd 00 01
row#1[7996] flag: ---D--, lock: 2, len=12
à entry
marked as delete
col 0; len 2;
(2): c1 04
col 1; len 6;
(6): 01 00 07 cd 00 02
row#2[7984] flag: ------, lock: 2, len=12
à New entry
added
col 0; len 2;
(2): c1 05
col 1; len 6;
(6): 01 00 07 cd 00 02
----- end of leaf
block dump -----
End
dump data blocks tsn: 4 file#: 4 minblk 2003 maxblk 2003
Observations:
Even for updates oracle will follows the same procedure as of deletes.
i.e
It will mark the old as DELETE and inserts new row for the updated value. If
there is any further row insertes into the same leaf block then it will delete
the rows entries that are marked as DELETED previously.
It
can be confirmed by treedump also:
----- begin tree dump
leaf: 0x10007d3
16779219 (0: nrow: 3
rrow: 2)
----- end tree dump
Current
rows = 2
Total
rows including that marked as DELETE = 3
Once
new rows are inserted into the same leaf blocks then oracle will delete the
rowentries that are marked as DELETE previously.