Oracle的体系结构中,关于存储结构大家应该都很熟悉了。

估计下面这张图大家都看得熟悉的不能再熟悉了。

Oracle中的段(r10笔记第81天)

    首先老三篇的内容我们换一种玩法,如果是一个11gR2的默认数据库环境,下面的这个语句会创建几个段。

create table test_seg (id number primary key,name varchar2(30),memo clob);

这个问题问住了不少的人,而似乎我也听到了不少意料之中的答案,如果认为是1个的,就是理解创建了一个表,那就是一个段了,这个段类型是TABLE,如果认为是2个的,那就是看到了里面有一个主键,那就是对应一个索引段,如果认为是3个的,那就是看到了LOB字段,不过还差一步,LOB其实是会创建两个段,一个是LOB段,一个是LOB索引段,结构化的数据是Oracle的强项,而如果加入半结构化的数据处理,就得额外花些功夫。而如果我们在11gR2的环境中,我们耳濡目染的而一个特性,延迟段创建,存在一个数据库参数segment_deferred_creation默认为true,即开启了延迟段创建,所以上面的语句不会创建任何的段。

SQL> select segment_name,segment_type from user_segments;

而我们插入一部分的数据,我们就插入近50万数据吧。insert into test_seg select level,'obj'||level,'' from dual connect by level<500000;

这样一来,问题就回归了,是4个段,其中SYS_IL开头的段是索引段,剩下SYS_开头的两个是LOB相关的段。

select segment_name,segment_type from user_segments;

怎么去理解这个段呢。

我们还是求助于user_segments来看看。

SQL> select segment_name,extents,blocks from user_segments

可以看到段TEST_SEG存在26个区块,含有1408个数据块。这些都是概览的信息。

如果想得到更细致一些的信息呢,那就是user_extents了。我们简化一下,只是查看segment_type为TABLE的区块信息。

SQL> select segment_name,segment_type,extent_id,bytes,blocks from user_extents  where segment_name='TEST_SEG' order by segment_name,extent_id ;

TEST_SEG             TABLE    0      65536          8

这里我们可以看到段级别对应的区是0-25,和user_segments中看到的26个区数据是一致的。

而这些区块的ID其实就是一个逻辑的编号,是基于段级别的划分。

同样上面的语句,我们简单改一下,查看segment_type为INDEX的区块信息。如下:

SEGMENT_NAME         SEGMENT_TYPE          EXTENT_ID      BYTES     BLOCKS

可以很明显看到区块的ID也是从0开始,比如0-7

这里就需要明白,这里的区块0是相对于这个segment_type为INDEX的segment为SYS_C0011978而言的。所以这里的值是一个相对的值,而不是绝对的。

而绝对的位置怎么查找呢,这得依赖于物理结构,能够定位的一个利器就是ROWID,我们取出1行数据来看看。

SQL> select dbms_rowid.ROWID_RELATIVE_FNO(rowid) as file#,dbms_rowid.ROWID_BLOCK_NUMBER(rowid) as block#,dbms_rowid.ROWID_ROW_NUMBER(rowid) as row#,a.* from test.test_seg a where rownum<2;

可以看到是4号数据文件,对应的数据块是134803 

要知道一个数据块里存放的数据基本上不是1行数据,而是相关的多行数据。

我们就可以做一个dump来看看。

 alter system dump datafile 4 block 134803;              

可以通过trace文件看到下面的内容:

 tab 0, row 0, @0x1f8a

目前存在3个字段,但是因为当前的LOB字段为空,就直接延迟创建了,只显示出来了两个字段。

而继续做一个update操作,提交事务。

SQL> update test_seg  set memo='aaa' where  rownum=1;

可以通过trace看到里面的内容已经大大不同,一个最大的变化就是LOB段的延迟创建情况,这个时候修改LOB段数据,所以就会重新初始化。

tab 0, row 0, @0x690

所以对于段来说,里面的信息对应的都是逻辑的概念,地址是逻辑地址,是相对的,而非绝对的。切莫认为一个区可以同时属于多个段。

相关文章: