11.14号-----本地管理表空间

一、名词解释

表空间--为数据库提供使用空间的逻辑结构,其对应物理结构是数据文件,一个表空间可以包含多个数据文件。

本地管理表空间(Locally Managed Tablespace 简称LMT)------8i以后出现的一种新的表空间的管理模式,通过本地图来管理表空间的空间使用。

字典管理表空间(Dictionary Managed Tablespace简称DMT)------8i以前包括以后都还可以使用的一种表空间管理模式,通过数据字典管理表空间的空间使用。

段(segment)-----数据库的一种逻辑结构,如表段,索引段,回滚段,段存在于表空间中,并对应一定的存储空间。

区间(extent)------段的存储可以分成一个或多个区间,每个区间占用一定数量的数据块,在本地管理的表空间中,表空间的Extent就对应段的Extent.

块(block)-----数据库的最小的存储单位,大小不同(根据操作系统的不同而不同)。

位(bit) ----本地管理表空间的空间管理单位,一个位可能等于一个区间,也可能多个位组成一个区间。

二、所谓的本地管理,就是指oracle不再利用数据字典来记录oracle表空间里面的区的使用状况,而是在每个表空间的数据文件的头部加入了一个位图区,在里面记录每个区的使用情况。每当一个区被 使用,或者被释放以供重新使用时,oracle都会更新数据文件头部的这个记录,反映这个变化。

语法:CREATE TABLESPACE 表空间名字

DATAFILE '数据文件详细信息'
[EXTENT MANAGEMENT { LOCAL
{AUTOALLOCATE | UNIFORM [SIZE INTETER [K|M] ] } } ]

关键字EXTENT MANAGEMENT LOCAL 指定这是一个本地化管理的表空间。对于系统表空间,只能在创建数据库的时候指定EXTENT MANGEMENT LOCAL,因为它是数据库创建时建立的第一个表空间。

在8i中,字典管理还是默认的管理方式,当选择了LOCAL关键字,即表明这是一个本地管理的表空间。当然还可以继续选择更细的管理方式:是AUTOALLOCATE 还是 UNIFORM.。若为AUTOALLOCATE,则表明让Oracle来决定区块的使用办法;若选择了UNIFORM,则还可以详细指定每个区块的大小,若不加指定,则为每个区使用1M大小。

Oracle之所以推出了这种新的表空间管理方法,让我们来看一下这种表空间组织方法的优点:

1. 本地化管理的表空间避免了递归的空间管理操作。而这种情况在数据字典管理的表空间是经常出现的,当表空间里的区的使用状况发生改变时,数据字典的表的信息发生改变,从而同时也使用了在系统表空间里的回滚段。

2. 本地化管理的表空间避免了在数据字典相应表里面写入空闲空间、已使用空间的信息,从而减少了数据字典表的竞争,提高了空间管理的并发性。

3. 区的本地化管理自动跟踪表空间里的空闲块,减少了手工合并自由空间的需要。

4. 表空间里的区的大小可以选择由Oracle系统来决定,或者由数据库管理员指定一个统一的大小,避免了字典表空间一直头疼的碎片问题。

5. 从由数据字典来管理空闲块改为由数据文件的头部记录来管理空闲块,这样避免产生回滚信息,不再使用系统表空间里的回滚段。因为由数据字典来管理的话,它会把相关信息记在数据字典的表里,从而产生回滚信息。

由于这种表空间的以上特性,所以它支持在一个表空间里边进行更多的并发操作,并减少了对数据字典的依赖。


三、本地管理表空间管理机制

表空间是一种为段(表,索引等)提供空间的逻辑结构,所以,当在表空间中增加,删除段的时候,数据库就必须跟踪这些空间的使用。

如下例所示,假定一个新创建的表空间包含了五个表

表一……表二……表三……表四……表五……未用空间

当我们删除表四的时候,就有如下结果

表一……表二……表三……空闲空间段……表五……未用空间

很明显,ORACLE需要有一个机制来管理表空间中各数据文件的这些分配的或未分配的空间,为了跟踪这些可以使用的空间(包括未分配使用的和可以重复使用的),对于每一个空间,我们必须知道:

1、这个可用空间位于什么数据文件

2、这个空间的尺寸是多大

3、如果它在用了,是哪一个段占用的这个空间

直到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方式的本地管理表空间

1、 先创建了一个本地管理的表空间,区间统一大小分配为64K

SQL> create tablespace demo
datafile '/ora01/oem/oemdemo01.dbf' size 10m
extent management local uniform size 64k;

2、 在该表空间中创建一个表

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)。

3、 获取该数据文件的文件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

4、 可以看到,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。

5、 同样我们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:: 0x01c0000aext#: 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是同样大小的,尽管你可能自定义了不同的存储参数。

6、 补充一些字典管理表空间的不同

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大小。


你可能感兴趣的:(表空间)