一、基本概念
一个表空间由若干个数据文件组成,表空间的属性可以从dba_tablespaces中获取:
SQL> desc dba_tablespaces;
TABLESPACE_NAME 名称
BLOCK_SIZE 一个blocik的大小,
INITIAL_EXTENT 分配给一个segment的第一个extent的大小,以字节为单位 NEXT_EXTENT,第二个extent的大小等于next的值,以后的next=前一next*(1+pctincrease/100)
MIN_EXTENTS segment 第一次创建时分配的extent数量
MAX_EXTENTS 一个segment最多的extent数量
PCT_INCREASE 见next_extent
MIN_EXTLEN
STATUS 状态 online|offline
CONTENTS permanent|temp|undo
LOGGING 是否记录redo
FORCE_LOGGING yes|no对表空间里的segment记录redo,即使该segment的logging属性logging
EXTENT_MANAGEMENT local | dictionary
ALLOCATION_TYPE system|uniform extent的分配类型:系统分配,或者是统一
PLUGGED_IN
SEGMENT_SPACE_MANAGEMENT 段管理 manual|auto 手动后自动
DEF_TAB_COMPRESSION
RETENTION
BIGFILE 是否大文件(10g)
-
本地管理或字典管理,两种方式的差别是表空间中extends的使用信息存放在表空间本身还是存在在数据字典中。本地管理比字典管理的性能要好,因为减少了访问数据字典的冲突。
-
段空间管理,自动管理使用位图管理段的可用空间,手动使用链表管理,需要设置pctused,freelists,freelists groups 等参数。通常自动比手动性能要好。
-
Extent的分配,可以是autoallocate (自动分配)或 uniform(统一大小)。自动分配模式下,extent的大小由系统决定,通常初始是8个block,之后逐渐增加,这样segment的空闲空间比较多。Uniform模式下,每个extent的大小是一致的,空闲的空间比较少。对于数据量增长比较稳定,而且知道增长量的大小,可设置合适的uniform大小。
-
用户表空间, extent建议使用本地管理,segment 建议使用自动管理
-
创建表空间的时候,如果指定extent management local,就不能再指定default storage子句。default storage子句包含了INITIAL_EXTENT、NEXT_EXTENT、MIN_EXTENTS、MIN_EXTENTS、MAX_EXTENTS、PCT_INCREASE这些参数。
-
9.2版本以上,若system表空间是local manage,则不能创建dictionary manage的表空间。
-
区管理和段管理方式在创建表空间时指定,之后不能再改,只有本地管理表空间可以使用自动的段空间管理方式。
二、数据文件的组织和段的空间分配
用得最多的是extent本地管理,segment自动管理的表空间。这种情况下,每个段使用位图来记录空间的使用情况,位图分为三个级别,L0,L1,L2 .其中第一个L0块就是段头,L0-L1-L2是一种树形结构。
BMB : bitmap block
以下是一个数据文件可能的例子:
|
Lmt使用(数据文件的前8个 block) |
|||||||
Segment 1 extent 0 |
First level bmb (L1) |
second lev el bmb (L2) |
Segment header(L0) |
Data block |
Data block |
Data block |
Data block |
Data block |
Segment 1 extent 1 |
Data block |
Data block |
Data block |
Data block |
Data block |
Data block |
Data block |
Data block |
Segment 1 extent 2 |
L2 |
Data block |
Data block |
Data block |
Data block |
Data block |
Data block |
Data block |
Segment 2 extent 0 |
L1 |
L2 |
Segment header(L0) |
Data block |
Data block |
Data block |
Data block |
Data block |
Segment 2 extent 1 |
Data block |
Data block |
Data block |
Data block |
Data block |
Data block |
Data block |
Data block |
…… |
…… |
…… |
…… |
…… |
…… |
…… |
…… |
…… |
每格为1个block,block size为8k,每个extent有8个block
每个数据文件最前面的8个块,是LMT用于管理extent分配的,每一个segmen的前三个block分别是bmb L1,bmb L2,和段头信息(L0),L1还会出现在其它extent中,但不是每个extent都会有L1。
三、通过直接路径插入和间接路径插入的对比来了解段的空间分配(在ITPUB晶晶小妹文章中的例子基础上)
直接路径插入与间接路径插入
-
采用直接路径插入方式向一个表插入记录时,不需要将该表原有的记录读入缓存,而直接在其物理数据块的高水位(hwm)后插入记录,因此提高了数据插入的效率,且不产生redo数据,而是通过高水位的值来进行回滚操作。使用直接路径插入的语句有create table as select 和inert 。
-
采用间接路径插入方式向一个表插入记录时,先将该表原有记录的数据块读入缓存,然后在缓存中插入新记录,数据块成为脏数据,再等待dbw进程将数据块写入数据文件(如checkpoint后)。
(一)准备
1.创建两个表。
SQL> create table aa(id number(4),name varchar2(5));
SQL> create table bb(id number(4),name varchar2(5));
2.aa表中插入数据
SQL> insert into aa values(1,'aa');
SQL> insert into aa values(2,'bb');
SQL> insert into aa values(3,'cc');
SQL> insert into aa values(4,'dd');
SQL> commit;
3.查看这些数据所在的数据块,可以看到这四条记录都位于文件4的463块上
SQL> select dbms_rowid.rowid_relative-fno(rowid),dbms_rowid.rowid_block_number(rowid) from aa;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) BMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
4 463
4 463
4 463
4 463
4.清空缓冲区,通过重新启动数据库来实现。使用alter system flush buffer cache不能完整清空。
SQL> shutdown immediate;
SQL> startup
5.查看缓冲区内aa、bb的数据块,可以看到这时缓冲区没有这两个表的数据块
SQL> select file#,block# from v$bh where objd=(select object_id from user_object
s where object_name='AA');
未选定行
SQL> select file#,block# from v$bh where objd=(select object_id from user_object
s where object_name='BB');
未选定行
5.再次查看aa记录所在的数据块
SQL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(owid) from aa;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) BMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
4 463
4 463
4 463
4 463
6.由于上一个查询操作,现在可以看到aa的数据块463和其它信息块已经读入缓存,bb也可类似查询。
SQL> select file#,block# from v$bh where objd=(select object_id from user_object
s where object_name='AA');
FILE# BLOCK#
4 461
4 464
4 459
4 459
4 462
4 460
4 463
SQL> select file#,block# from v$bh where objd=(select object_id from user_object
s where object_name='BB');
FILE# BLOCK#
4 467
4 467
7.通过alter system dump datafile 4 block 467,可以看到这是bb的块头,且高水位为468,使用了3个块。
...
frmt: 0x02 chkval: 0x6632 type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 8
last map 0x00000000 #maps: 0 offset: 2716
Highwater:: 0x010001d4 ext#: 0 blk#: 3 ext size: 8
(二)直接路径插入
1、直接插入
SQL> insert into BB select * from aa;
SQL> commit;
2、查询,可以看到,bb的数据块468并没有在缓存中:
SQL> select file#,block# from v$bh where objd=(select object_id from user_object
s where object_name='BB');
FILE# BLOCK#
4 467
4 467
4 465
SQL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(r
owid) from BB;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) BMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
4 468
3、465块通过dump出来看,是‘FIRST LEVEL BITMAP BLOCK’,也就是段自动管理使用的位图块L1,这是因为插入数据后要更新位图块信息。而467块显示该segment已用块数变为4;
465 dump:
...
frmt: 0x02 chkval: 0x0000 type: 0x20=FIRST LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
467 dump:
...
frmt: 0x02 chkval: 0x0000 type: 0x23=PAGETABLE SEGMENT HEADER
Hex dump of block: st=0, typ_found=1
Extent Header:: spare1: 0 spare2: 0 #extents: 1 #blocks: 8
last map 0x00000000 #maps: 0 offset: 2716
Highwater:: 0x010001d5 ext#: 0 blk#: 4 ext size: 8
(二)间接路径插入
1、间接插入
SQL> insert into BB select * from aa;
SQL> commit;
2、查看
SQL> select file#,block# from v$bh where objd=(select object_id from user_object
s where object_name='BB');
FILE# BLOCK#
4 469
4 472
4 467
4 467
4 470
4 465
4 468
4 471
4 466
SQL> select dbms_rowid.rowid_relative_fno(rowid),dbms_rowid.rowid_block_number(rowid) from BB;
DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) BMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
4 468
4 468
4 468
4 468
4 472
4 472
4 472
4 472
可以看到,bb的数据块468,472都已经在缓存中
3、 dump 467
...
Highwater:: 0x010001d9 ext#: 0 blk#: 8 ext size: 8
...
#blocks in seg. hdr's freelists: 0
#blocks below: 8
mapblk 0x00000000 offset: 0
Level 1 BMB for High HWM block: 0x010001d1
Level 1 BMB for Low HWM block: 0x010001d1
Segment Type: 1 nl2: 1 blksz: 8192 fbsz: 0
L2 Array start offset: 0x00001434
First Level 3 BMB: 0x00000000
L2 Hint for inserts: 0x010001d2
Last Level 1 BMB: 0x010001d1
Last Level II BMB: 0x010001d2
Last Level III BMB: 0x00000000
Map Header:: next 0x00000000 #extents: 1 obj#: 52657 flag: 0x10000000
Inc # 0
Extent Map
0x010001d1 length: 8
Auxillary Map
Extent 0 : L1 dba: 0x010001d1 Data dba: 0x010001d4
Second Level Bitmap block DBAs
高水位变为473,已用块变为8,bmb L1 地址 0x010001d1(file 4,block 465), bmb L2 地址 0x010001d2(file 4,block 466),数据块开始位置0x010001d4(file 4,block 468)