oracle中的逻辑结构,oracle的逻辑结构

a4c26d1e5885305701be709a3d33442f.png

这是一张非常基本同时也是非常重要的结构图。物理结构很简单,就是操作系统物理块组成数据文件,对于操作系统来说,数据文件跟其他非数据库文件没有区别。重点是逻辑结构。

一、表空间

从9i开始,oracle支持不同块大小的表空间,也就是说同一个数据库中,不同表空间的数据块大小可以不一样。假设默认8k的话,还可以创建比如4k、16k、32k、64k等大小的表空间。不过如果有不同块大小的表空间,请记得为它们设置不同的db_nk_cache_size参数,以为这些表空间的数据访问分配内存。

从10g开始,oracle支持重命名表空间,语法是alter tablespace

rename to

;这个操作在传输表空间时非常有用,当源和目标的表空间名称不一致时,通过此命令可以方便地更名,这是一大进步。

二、段(segment)

参考上图,一个段可以跨越多个数据文件,但只能在一个表空间中。一个段由多个区(extent)组成。每一个段都有一个单独的data_object_id对应。这里需要额外说明一下data_object_id和object_id的区别。简单的说,object_id对应的是对象,而data_object_id对应的是段。比如一个procedure有object_id,但没有data_object_id,因为它不是段。因为每一个段都唯一对应一个表空间,而每一个段都拥有自己独一无二的data_object_id,所以通过data_object_id,就能唯一定位这个段所在的表空间,这就是rowid的原理。

这里做一个实验,来说明data_object_id和object_id的区别以及一些操作对data_object_id的影响。首先创建一张分区表

SQL>create table part_test(id number,create_time

date)

partition

by range (id)

(partition

part1 values less than (100),

partition part2 values less than (200),

partition

part3 values less than (maxvalue));

看一下没有数据时的情况

SQL>select

object_name,subobject_name,object_type,object_id,data_object_id

from user_objects where object_name = 'PART_TEST';

OBJECT_NAME SUBOBJECT_NAME OBJECT_TYPE OBJECT_ID DATA_OBJECT_ID

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

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

PART_TEST TABLE 73205

PART_TEST PART1 TABLE

PARTITION 73206 73206

PART_TEST PART2 TABLE

PARTITION 73207 73207

PART_TEST PART3 TABLE

PARTITION 73208 73208

可以看出,初始没有数据的时候,data_object_id和object_id一样。考虑到data_object_id是记录了数据存放的位置,我们看一下先插入数据,再将表truncate之后的情况。

SQL> insert into part_test values(1,sysdate);

1 row created.

SQL> insert into part_test

values(101,sysdate+1);

1 row created.

SQL> commit;

Commit complete.

SQL> truncate table part_test;

Table truncated.

SQL> select

object_name,subobject_name,object_type,object_id,data_object_id

from user_objects where object_name = 'PART_TEST';

OBJECT_NAME SUBOBJECT_NAME OBJECT_TYPE OBJECT_ID DATA_OBJECT_ID

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

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

PART_TEST PART3 TABLE

PARTITION 73208 73208

PART_TEST PART2 TABLE

PARTITION 73207 73211

PART_TEST PART1 TABLE

PARTITION 73206 73210

PART_TEST TABLE 73205

可以看出,有数据的段,对应的data_object_id改变了,这是因为truncate之后,oracle重新分配了这些段存储数据的空间,因此改变了data_object_id。而没有数据的段,data_object_id没有改变,因为oracle并没有对这些段重新分配数据存储空间。

三、区(extent)

一个区由连续的块组成。这里要强调的就是连续。因此,一个区是不能跨数据文件的(参见上图跟数据文件相连的那条线)

四、块(block)

这是oracle存取数据最小的单位,在建立数据库的时候指定,一旦指定则无法修改。(但在9i之后可以创建不同块大小的表空间,一定程度上解决了这个问题。)

一个块除了了块头、表目录和行目录之外的空间,都可以用来存放数据。按照默认8k大小的块来说,这部分可以真正存放数据的空间是8096字节。然后因为各种其他开销,每行数据的最小长度大约是11个字节,也就是说,每个块最大存放的行数理论值是8096/11=736行。我们可以做个试验来验证一下。

SQL> create table block_test(a varchar2(1)) pctfree

0 tablespace datatb;

Table created.

SQL> select object_id from user_objects where

object_name = 'BLOCK_TEST';

OBJECT_ID

----------

73213

SQL> select spare1 from sys.tab$ where

OBJ#=73213;

SPARE1

----------

736

可以看到,当我们创建了一个pctfree=0(表示不预留空间,块中所有可以存放数据的空间都用来存放数据)的表时,最大存放行数理论值为736,跟我们的计算一致。那么实际可以存放多少呢?我们继续做下去。

SQL> begin

2 for i in 1 .. 10000

loop

3 insert into block_test

values('1');

4 end loop

5 commit;

6 end;

7 /

PL/SQL procedure successfully completed.

使用一个循环,向表中插入10000条数据,每条数据只有一个字节。

SQL> select file#,block#,count(*)

2 from

(select dbms_rowid.rowid_relative_fno(rowid) file#,

3 dbms_rowid.rowid_block_number(rowid) block#

4 from block_test)

5 group by

file#,block#;

然后我们通过上面的语句来看这些数据的分布

FILE# BLOCK# COUNT(*)

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

4 209 733

4 212 733

4 203 733

4 214 733

4 206 733

4 215 733

4 205 733

4 208 733

4 210 733

4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值