表空间是一种为段(表,索引等)提供空间的逻辑结构,因此,当在表空间中增长,删除段的时候,数据库就必须跟踪这些空间的使用。
以下例所示,假定一个新建立的表空间包含了五个表
表一……表二……表三……表四……表五……未用空间
当咱们删除表四的时候,就有以下结果
表一……表二……表三……空闲空间段……表五……未用空间
很明显,ORACLE须要有一个机制来管理表空间中各数据文件的这些分配的或未分配的空间,为了跟踪这些可使用的空间(包括未分配使用的和能够重复使用的),
对于每个空间,咱们必须知道:
一、这个可用空间位于什么数据文件
二、这个空间的尺寸是多大
三、若是它在用了,是哪个段占用的这个空间
直到8i以前,全部的表空间都是采用字典管理模式,为了确保能保存以上的信息,ORACLE用了两个数据字典表:UET$(已使用的区间)或FET$(空闲空间):
SQL> desc UET$
Name Null? Type
SEGFILE# NOT NULL NUMBER
SEGBLOCK# NOT NULL NUMBER | The segment that uses this space
EXT# NOT NULL NUMBER
TS# NOT NULL NUMBER | The tablespace ID and the file
FILE# NOT NULL NUMBER | ID for that tablespace
BLOCK# NOT NULL NUMBER
LENGTH NOT NULL NUMBER | The location and size of the chunk
SQL> desc FET$
Name Null? Type
TS# NOT NULL NUMBER | The tablespace ID and the file
FILE# NOT NULL NUMBER | ID for that tablespace
BLOCK# NOT NULL NUMBER
LENGTH NOT NULL NUMBER | The location and size of the chunk
查询该表能够看到,每一个使用空间或空闲空间(不必定是一个extent,能够是多个extent)都在该表中对应了一行。它的工做方式是当一个段
被删除的时候,ORACLE就移动UET$中相应的行到FET$,这个过程的发生是连续的,并且可能发生等待。当并发性很高的时候,数据字典的争用
就来了。
另外有一个问题就是,当表的空间很不连续或表空间有大量的碎片引发这两个表的增大,那么也就会引发数据库性能上的降低。
本地管理表空间正是为了解决这一问题来的,在表空间的空间管理上,ORACLE将存储信息保存在表空间的头部的位图中,而不是保存在数据字典中。
经过这样的方式,在分配回收空间的时候,表空间就能够独立的完成操做也不用与其它对象关系。
下面就让咱们进入到本地管理表空间的内部,看看ORACLE是怎么实现这一工做的。
Uniform方式的本地管理表空间
一、 先建立了一个本地管理的表空间,区间统一大小分配为64K
SQL> create tablespace demo
datafile '/ora01/oem/oemdemo01.dbf' size 10m
extent management local uniform size 64k;
二、 在该表空间中建立一个表
SQL>create table demotab ( x number ) tablespace demo
storage ( initial 1000K next 1000k );
咱们经过查询该表
SQL> select t.table_name,t.initial_extent,t.next_extent from user_tables t where t.table_name = 'DEMOTAB';
TABLE_NAME INITIAL_EXTENT NEXT_EXTENT
DEMOTAB 1024000 65536
能够发现,该表的存储参数并非咱们指定的参数INITIAL_EXTENT,而是uniform size的整数倍,NEXT_EXTENT则等于uniform size。咱们从该
查询就也能够看到以下状况
SQL>select count(*) from user_extents where segment_name = 'DEMOTAB';
COUNT(*)
16
也就是说,该表在该表空间中已经存在16个extent,而不是一个extent(这是与字典管理的差异,若是是字典管理的表空间,若是建立以上的表,该查询的结果是1)。
三、 获取该数据文件的文件ID
SQL> col name format a30 trunc
SQL> select file#, name from v$datafile;
File# NAME
-----
1 /oras1/oem/oemsystem01.dbf
2 /oras3/oem/oemundo01.dbf
3 /ora01/oem/oemoem_repository01
4 /ora01/oem/oemrcat01.dbf
5 /ora01/oem/oemdemo01.dbf
咱们能够检查uet$与fet$
SQL> select count(*) from uet$ where file# = 5;
COUNT(*)
0
SQL> select count(*) from fet$ where file# = 5;
COUNT(*)
0
四、 能够看到,ORACLE没有在这两个表中保存任何信息,如今咱们dump该数据文件的第三个块。
SQL> alter system dump datafile 5 block 3;
System altered.
查看DUMP文件,有以下信息
Start dump data blocks tsn: 5 file#: 5 minblk 3 maxblk 3
buffer tsn: 5 rdba: 0x01400003 (5/3)
scn: 0x0000.202f7a6f seq: 0x01 flg: 0x00 tail: 0x7a6f1e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
File Space Bitmap Block:
BitMap Control:
RelFno: 5, BeginBlock: 9, Flag: 0, First: 16, Free: 63472
FFFF000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
.....
注意其中的FFFF00,,这是16进制的表现方法,咱们转换为二进制,有
1111,1111,1111,1111,0000,0000
发现这里有16个1,每个1就是一个位(bit),表明64K,也就表明了该表空间有已经分配了的16个extent,若是咱们将该表扩展,将又有什么
结果呢?
SQL> alter table demotab allocate extent;
Table altered.
SQL> alter table demotab allocate extent;
Table altered.
SQL> alter table demotab allocate extent;
Table altered.
这样以后,咱们应该有19个extent了,再dump第三个块
Start dump data blocks tsn: 5 file#: 5 minblk 3 maxblk 3
buffer tsn: 5 rdba: 0x01400003 (5/3)
scn: 0x0000.202f7c64 seq: 0x01 flg: 0x00 tail: 0x7c641e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
File Space Bitmap Block:
BitMap Control:
RelFno: 5, BeginBlock: 9, Flag: 0, First: 19, Free: 63469
FFFF07 0000000000 0000000000000000 0000000000000000 0000000000000000
除了之前的FFFF,如今多了07,怎么解释呢?
07转换为二进制为0000,0111,可是仍是不够解释以上的状况,这里咱们没有考虑到字节交换的状况,由于以上FF交换后仍是FF,可是若是是07
,咱们就必须考虑字节交换(由于计算机是一个字节一个字节的写,一个字节占两位固然是先写后面了,如从01到0F到FF为止。若是咱们明白
了,那么FFFF07转换为二进制为 1111,1111,1111,1111,0000,0111。
每一个字节交换得
1111,1111,1111,1111,1110,0000
能够发现,这里有19个1,也就是19个位(bit),表明了如今的19个extent。
五、 一样咱们dump该数据文件第9个块,则有
Start dump data blocks tsn: 5 file#: 5 minblk 9 maxblk 9
buffer tsn: 5 rdba: 0x01400003 (5/3)
scn: 0x0000.202f7c64 seq: 0x01 flg: 0x00 tail: 0x7c641e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
Extent Control Header
Extent Header:: spare1: 0 space2: 0 #extents: 16 #blocks: 127
last map 0x00000000 #maps: 0 offset: 4128
Highwater:: 0x01c0000a ext#: 0 blk#: 0 ext size: 7
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
Disk Lock:: Locked by scn: 0x0006.012.00000017
Map Header:: next 0x00000000 #extents: 16 obj#: 3090 flag: 0x40000000
Extent Map
0x01c0000a length: 7
0x01c00011 length: 8
0x01c00019 length: 8
0x01c00021 length: 8
0x01c00029 length: 8
0x01c00031 length: 8
0x01c00039 length: 8
0x01c00041 length: 8
0x01c00049 length: 8
0x01c00051 length: 8
0x01c00059 length: 8
0x01c00061 length: 8
0x01c00069 length: 8
0x01c00071 length: 8
0x01c00079 length: 8
0x01c00081 length: 8
nfl = 1, nfb = 1 typ = 1 nxf = 0
SEG LST:: flg: UNUSED lhd: 0x00000000 ltl: 0x00000000 End dump data blocks tsn: 5 file#: 5 minblk 9 maxblk 9
这是该数据文件中表DEMOTAB的表头(一个块)信息,从这里能够看到,该表从第9个块开始使用Highwater:: 0x01c0000a已是第10个块了,从以上列表,咱们也能清楚的看到,该表耗费了16个区间。
因为该表是数据文件的第一个表,因此位图区占用从3到8共6个块,加上前面两个文件头,也就是说,在数据文件头部共8个块用于系统消耗。
若是咱们的db_block_size为8192,那么很明显,占用的空间为64K(注意:对于不一样的块大小,文件头部的块个数与大小可能会不同)。
也由于仅仅操做数据文件头部几个块,不用操做数据字典,因此ORACLE在本地管理的表空间中添加,删除段的时候,效率要比字典管理的表空间快。特别是在并发性很强的空间请求中。
ORACLE经过强制性的手段使本地管理表空间中的全部Extent是一样大小的,尽管你可能自定义了不一样的存储参数。
六、 补充一些字典管理表空间的不一样
a. 若是是字典管理,表空间中的表的区间的大小取决于表的存储参数,若是没有定义,则取表空间的通用存储参数。因此每一个表的区间大小能够不同。
b. 若是不指定表的最少区间数,那么默认建立的时候,该表只有一个区间,而不是多个区间。
c. 字典管理的文件头只占用一个块,第一个表的HWM应当是Highwater:: x01c00003,关于这个能够本身dump该数据文件查看。
Autoallocate的本地管理表空间
在自动分配的本地管理的表空间中,区间尺寸可能由如下尺寸组成64k, 1m, 8m, 64m 甚至是256m。可是无论多大,都有一个通用尺寸64k,因此64K就是该表空间的位大小。
SQL> create tablespace dummy
datafile 'c:\dummy01.dbf' size 100m
autoallocate;
Tablespace created.
SQL> create table x1 (x number)
tablespace dummy
storage (initial 50M);
Table created.
SQL> select file# from v$datafile where name like '%DUMMY%';
FILE#
12
SQL> select extents from user_segments
where segment_name = 'X1' ;
EXTENTS
50
SQL> alter system dump datafile 12 block 3;
System altered.
*** SESSION ID11.59) 2002-11-22 10:37:35.000
Start dump data blocks tsn: 19 file#: 12 minblk 3 maxblk 3
buffer tsn: 19 rdba: 0x03000003 (12/3)
scn: 0x0000.00f2959b seq: 0x01 flg: 0x00 tail: 0x959b1e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
File Space Bitmap Block:
BitMap Control:
RelFno: 12, BeginBlock: 9, Flag: 0, First: 800, Free: 62688
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFF
FFFFFFFF00000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
能够看到该表实际只有50个区间(extent),可是有800个位(bit)
50*1024=800*64
还能够看出,位大小并不等于extent大小。