rebuild index 排序

好贴,http://www.itpub.net/viewthread.php?tid=205422&extra=&page=1 这里摘录整理一下。[@more@]

Eagle:

rebuild index为何要排序

我们都知道索引是有序的存储

然而在block内部,实际上索引键值的存储是无序的

比如说,你先存入了1,3

即使以后增加了一个2

那么在同一个数据块内部,数据库也不会去动1,3的存储

在读取的时候,oracle可以作简单的块内排序,进行有序的读取输出

在重建索引的时候

Oracle显然不会按照1,2,3..........的索引顺序来读出索引内容

因其代价高昂

Oracle实际执行的是Fast Full Scan

按顺序读取block

这样读取出来的数据需要重新sort

排序,然后重构索引

这个重构的索引在物理存储上比原来更为有序

总结:

1、索引的存储是,块内无序,块间有序

2、索引叶子节点内部没有存在 链表状结构来维护顺序,则row# 总是可能发生变化的。记录在块内物理上是无序的,但是在逻辑上通过row#来表达了顺序。

3、rebulid index 要考虑 rebuild后新的index大小,如果rebuild online 会有一些临时信息占用空间,这些都在index所在表空间上。另外,rebuild需要排序,一般sort area size是不够用的,会用到temp表空间。

4.如果是非ONLINE方式,通常会对该表设置一个表级共享(DML)锁,那么就对DML语句冲突,
如果设置ONLINE ,(会使用临时日志IOT表来记录中间改变的数据),但要使用两倍于传统方法的空间.表会变成行级共享锁,在创建索引或者ALTER完成后,对临时日志表与基表进行MERGE
注意并行处理,DDL,位图索引不能使用ONLINE。
5.从索引开始rebuild online开始的那一刻起,oracle会先创建一个SYS_JOURNAL_xxx的系统临时日志表,结构类似于mlog$_表,
通过内部触发器,记录了开始rebuild索引时表上所发生的改变的记录,当索引已经创建好之后,新数据将直接写入索引,
只需要把SYS_JOURNAL_xxx日志表中的改变维护到索引中即可。
6.rebuild index 是读取老的index的,但是 rebuild index online 是读取基表的。

dlinger:

我作了两个试验。

我的index大小为7M左右。

首先,我将index所在的tablespace只开到10M,临时表空间较大,

rebuild 时报无法在index所在的tablespace上扩展temp 段。

将表空间增大,rebuild成功。

在将临时表空间只开到5M,表空间开到20Mrebuild就报无法在temp表空间上扩展,将临时表空间增大到10Mrebuild成功

今天找了个时间做了把实验

SQL> select * from test_index;

ID NAME

--------------------------------------- --------------------

1 aa

2 aa

3 aa

35 aa

32 bb

SQL> select dump(id) from test_index;

DUMP(ID)

--------------------------------------------------------------------------------

Typ=2 Len=2: 193,2

Typ=2 Len=2: 193,3

Typ=2 Len=2: 193,4

Typ=2 Len=2: 193,36

Typ=2 Len=2: 193,33

SQL> alter system dump datafile 15 block 42 ;

*** 2004-04-05 11:49:19.947

Start dump data blocks tsn: 14 file#: 15 minblk 42 maxblk 42

buffer tsn: 14 rdba: 0x03c0002a (15/42)

scn: 0x0000.00196f9b seq: 0x01 flg: 0x00 tail: 0x6f9b0601

frmt: 0x02 chkval: 0x0000 type: 0x06=trans data

Block header dump: 0x03c0002a

Object id on Block? Y

seg/obj: 0x682f csc: 0x00.196f99 itc: 2 flg: - typ: 2 - INDEX

fsl: 0 fnx: 0x0 ver: 0x01

Itl Xid Uba Flag Lck Scn/Fsc

0x01 xid: 0x0000.000.00000000 uba: 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

0x02 xid: 0x0004.050.000002ed uba: 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

Leaf block dump

===============

header address 60386396=0x3996c5c

kdxcolev 0

kdxcolok 0

kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y

kdxconco 2

kdxcosdc 0

kdxconro 5

kdxcofbo 46=0x2e

kdxcofeo 7976=0x1f28

kdxcoavs 7930

kdxlespl 0

kdxlende 0

kdxlenxt 0=0x0

kdxleprv 0=0x0

kdxledsz 0

kdxlebksz 8036

row#0[8024] flag: -----, lock: 0

col 0; len 2; (2): c1 02

col 1; len 6; (6): 03 c0 00 0a 00 00

row#1[8012] flag: -----, lock: 0

col 0; len 2; (2): c1 03

col 1; len 6; (6): 03 c0 00 0a 00 01

row#2[8000] flag: -----, lock: 0

col 0; len 2; (2): c1 04

col 1; len 6; (6): 03 c0 00 0a 00 02

row#3[7988] flag: -----, lock: 0

col 0; len 2; (2): c1 21

col 1; len 6; (6): 03 c0 00 0a 00 04

row#4[7976] flag: -----, lock: 0

col 0; len 2; (2): c1 24

col 1; len 6; (6): 03 c0 00 0a 00 03

----- end of leaf block dump -----

SQL> insert into test_index values(21,'cs');

commit;

SQL> alter system dump datafile 15 block 42 ;

*** 2004-04-05 12:27:13.381

Start dump data blocks tsn: 14 file#: 15 minblk 42 maxblk 42

buffer tsn: 14 rdba: 0x03c0002a (15/42)

scn: 0x0000.00196f9f seq: 0x01 flg: 0x02 tail: 0x6f9f0601

frmt: 0x02 chkval: 0x0000 type: 0x06=trans data

Block header dump: 0x03c0002a

Object id on Block? Y

seg/obj: 0x682f csc: 0x00.196f99 itc: 2 flg: - typ: 2 - INDEX

fsl: 0 fnx: 0x0 ver: 0x01

Itl Xid Uba Flag Lck Scn/Fsc

0x01 xid: 0x0000.000.00000000 uba: 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000

0x02 xid: 0x0005.04b.000002e3 uba: 0x00800815.0090.35 --U- 1 fsc 0x0000.00196f9f

Leaf block dump

===============

header address 60386396=0x3996c5c

kdxcolev 0

kdxcolok 0

kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y

kdxconco 2

kdxcosdc 0

kdxconro 6

kdxcofbo 48=0x30

kdxcofeo 7964=0x1f1c

kdxcoavs 7916

kdxlespl 0

kdxlende 0

kdxlenxt 0=0x0

kdxleprv 0=0x0

kdxledsz 0

kdxlebksz 8036

row#0[8024] flag: -----, lock: 0

col 0; len 2; (2): c1 02

col 1; len 6; (6): 03 c0 00 0a 00 00

row#1[8012] flag: -----, lock: 0

col 0; len 2; (2): c1 03

col 1; len 6; (6): 03 c0 00 0a 00 01

row#2[8000] flag: -----, lock: 0

col 0; len 2; (2): c1 04

col 1; len 6; (6): 03 c0 00 0a 00 02

row#3[7964] flag: -----, lock: 2

col 0; len 2; (2): c1 16

col 1; len 6; (6): 03 c0 00 0a 00 05

row#4[7988] flag: -----, lock: 0

col 0; len 2; (2): c1 21

col 1; len 6; (6): 03 c0 00 0a 00 04

row#5[7976] flag: -----, lock: 0

col 0; len 2; (2): c1 24

col 1; len 6; (6): 03 c0 00 0a 00 03

----- end of leaf block dump -----

End dump data blocks tsn: 14 file#: 15 minblk 42 maxblk 42

--------------------------------------------------------------------------------

Biti_rainy

如上红色部分,新记录的插入并没有导致物理位置发生变化。如果要维护块内顺序,则参考 在表数据块中是 row dictionary 有另外一个地方维护这个结构。但这在index dump中是看不出来这样的结构的,只能看到这里是根据顺序输出的trace。我曾经想过这样一个问题,那就是,如果要维护这个顺序,假如索引块中存在100row记录,新插入一个记录进来(很显然这里每个row 消耗了12个字节,应该就是 rowid 6 , col length 1,col 2,lock 1,flag 1, row# 1) 这意味着新插入一条记录将可能修改很多记录的row#吗?

其实,如果能在变化中把索引block的二进制直接读出来观察变化应该可以立即断定。

很显然,索引叶子节点内部没有存在 链表状结构来维护顺序,则row# 总是可能发生变化的。记录在块内物理上是无序的,但是在逻辑上通过row#来表达了顺序。我们可以假想一种顺序读出数据的方式,block内部存在记录 kdxconro ,则读出的时候建立结构数组 index_struc[kdxconro] ,当读到行号为 row# 的记录的时候就放入 index_struc[row#] 这样实现数据的有序读取, 当写入的时候,无论如何,可能去更改很多记录的 row#

请使用浏览器的分享功能分享到微信等