柔中带刚,刚中带柔,淫荡中富含柔和,刚猛中荡漾风骚,无坚不摧,无孔不入!
全部博文(1669)
分类: Oracle
2012-11-22 15:19:47
2012-11-22 11:07:58| 分类: linux下Oracle 10 | 标签: |字号大中小
Oracle的存储分为四个层次,Block、Extent、Segment和Tablespace。Oracle分配空间到Segment时,是将一组连续的Block添加到Segment,这组连续的Block称作一个Extent。
对于已经分配和还未分配的Extent的元数据可能存放在数据字典中(字典管理表空间),也可能存放在tablespace header中(本地管理表空间)。
可以通过以下语句来查看当前的表空间是本地管理还是字典管理:
select tablespace_name, extent_management, allocation_type from dba_tablespaces;
SYSTEM LOCAL SYSTEM
UNDOTBS1 LOCAL SYSTEM
SYSAUX LOCAL SYSTEM
TEMP LOCAL UNIFORM
USERS LOCAL SYSTEM
TEST LOCAL UNIFORM
字典管理表空间(DMT)
Oracle使用SYS.FET$表来记录空闲空间,使用SYS.UET$表来记录已经使用过的空间。当从表空间分配新的Extent时,必须先获得space transaction(ST) enqueue latch后才能插入或删除SYS.FET$和SYS.UET$表。在特定的时间内,只有一个进程能获得ST enqueue,这通常会引起竞争和等待。
可以使用下列语句来创建一个DMT
CREATE TABLESPACE ts1 DATAFILE '/oradata/ts1_01.dbf' SIZE 50M
EXTENT MANAGEMENT DICTIONARY
DEFAULT STORAGE ( INITIAL 50K NEXT 50K MINEXTENTS 2 MAXEXTENTS 50 PCTINCREASE 0);
DEFAULT STROAGE:该选项只对DMT有效。使用它可以指定在该DMT中创建的所有对象是否压缩(COMPRESS/NOCOMPRESS)及其默认参数。
MINIMUM EXTENT:指定extent的最小大小。
TEMPORARY:创建临时表空间。创建临时表空间有两种语法:CREATE TEMPORARY TABLESPACES TEMPFILE和CREATE TABLESPACE TEMPORARY。最好CREATE TEMPORARY TABLESPACES TEMPFILE来创建临时表空间,使用此方法创建的表空间只能是LMT。如果你想创建DMT临时表空间可以使用CREATE TABLESPACE TEMPORARY。使用CREATE TEMPORARY TABLESPACES TEMPFILE创建临时表空间,不能使用AUTOALLOCATE,默认为UNIFORM。
本地管理表空间(LMT)
使用LMT,每个表空间使用表空间数据文件中的一个bitmap结构来管理空闲和已使用的空间的元数据信息。每一bit对应一个数据库block或一组blcok。可以通过下面任一语句建立一个LMT
CREATE TABLESPACE ts2 DATAFILE '/oradata/ts2_01.dbf' SIZE 50M
EXTENT MANAGEMENT LOCAL AUTOALLOCATE;
CREATE TABLESPACE ts3 DATAFILE '/oradata/ts3_01.dbf' SIZE 50M
EXTENT MANAGEMENT LOCAL UNIFORM SIZE 128K;
AUTOALLOCATE:使用AUTOALLOCATE,则extent的大小是系统管理的,Oracle在分配下一个extent时,会选择一个最佳的extent大小。extent大小包含从64KB到1MB、8MB一直到64MB,随着segment的增长oracle会选择更大的extent。
UNIFORM:使用UNIFORM指定extent大小,则Oracle会根据此数字创建下一个extent。默认值是1M。LMT表空间中创建object时,不能覆盖该uniform extent size。
本地管理表空间的好处:
----不需要使用recursive sql访问UET$和FET$
----消除了对于UET$和FET$的竞争(single ST enqueue)
----不用定期连接空闲空间,LMT会自动跟踪相邻的空闲空间。
----使用LMT时,分配extent只是改变segment header中的bitmap structure,不会产生回滚信息。
表空间(Tablespace):为数据库提供使用空间的逻辑结构,其对应物理结构是数据文件,一个表空间可以包含多个数据文件。
本地管理表空间(Locally Managed Tablespace简称LMT):8i以后出现的一种新的表空间的管理模式,通过本地位图来管理表空间的空间使用。
字典管理表空间(Dictionary-Managed Tablespace简称DMT):8i以前包括以后都还可以使用的一种表空间管理模式,通过数据字典管理表空间的空间使用。
段(Segment):数据库一种逻辑结构,如表段,索引段,回滚段等,段存在于表空间中,并对应一定的存储空间。
区间,可以简称区(Extent):段的存储可以分成一个或多个区间,每个区间占用一定数量的数据块(block),在本地管理的表空间中,表空间的Extent就对应段的Extent。
块(Block):数据库最小的存储单位,在本文中Block的大小约定为8192字节。
位(Bit):本地管理表空间的空间管理单位,一个位可能等于一个区间,也可能多个位组成一个区间。
2 本地管理表空间
2.1 语法
在Oracle8I的版本中,Oracle推出了一种全新的表空间管理方式:本地化管理的表空间。所谓本地化管理,就是指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大小。
2.2 本地管理优点
1. 本地化管理的表空间避免了递归的空间管理操作。而这种情况在数据字典管理的表空间是经常出现的,当表空间里的区的使用状况发生改变时,数据字典的表的信息发生改变,从而同时也使用了在系统表空间里的回滚段。
2. 本地化管理的表空间避免了在数据字典相应表里面写入空闲空间、已使用空间的信息,从而减少了数据字典表的竞争,提高了空间管理的并发性
3. 区的本地化管理自动跟踪表空间里的空闲块,减少了手工合并自由空间的需要。
4. 表空间里的区的大小可以选择由Oracle系统来决定,或者由数据库管理员指定一个统一的大小,避免了字典表空间一直头疼的碎片问题。
5. 从由数据字典来管理空闲块改为由数据文件的头部记录来管理空闲块,这样避免产生回滚信息,不再使用系统表空间里的回滚段。因为由数据字典来管理的话,它会把相关信息记在数据字典的表里,从而产生回滚信息。
由于这种表空间的以上特性,所以它支持在一个表空间里边进行更多的并发操作,并减少了对数据字典的依赖。
3 本地管理表空间管理机制
表空间是一种为段(表,索引等)提供空间的逻辑结构,所以,当在表空间中增加,删除段的时候,数据库就必须跟踪这些空间的使用。
如下例所示,假定一个新创建的表空间包含了五个表
表一……表二……表三……表四……表五……未用空间
当我们删除表四的时候,就有如下结果
表一……表二……表三……空闲空间段……表五……未用空间
很明显,ORACLE需要有一个机制来管理表空间中各数据文件的这些分配的或未分配的空间,为了跟踪这些可以使用的空间(包括未分配使用的和可以重复使用的),对于每一个空间,我们必须知道:
1、这个可用空间位于什么数据文件
2、这个空间的尺寸是多大
3、如果它在用了,是哪一个段占用的这个空间
直到8i之前,所有的表空间都是采用字典管理模式,为了确保能保存以上的信息,ORACLE用了两个数据字典表:UET$(已使用的区间)或FET$(空闲空间):
SQL> desc UET$
Name Type Nullable Default Comments
--------- ------ -------- ------- --------
SEGFILE# NUMBER
SEGBLOCK# NUMBER
EXT# NUMBER
TS# NUMBER
FILE# NUMBER
BLOCK# NUMBER
LENGTH NUMBER
SQL> desc FET$
Name Type Nullable Default Comments
------ ------ -------- ------- --------
TS# NUMBER
FILE# NUMBER
BLOCK# NUMBER
LENGTH NUMBER
查询该表可以看到,每个使用空间或空闲空间(不一定是一个extent,可以是多个extent)都在该表中对应了一行。它的工作方式是当一个段被删除的时候,ORACLE就移动UET$中相应的行到FET$,这个过程的发生是连续的,而且可能发生等待。当并发性很高的时候,数据字典的争用就来了。另外有一个问题就是,当表的空间很不连续或表空间有大量的碎片引起这两个表的增大,那么也就会引起数据库性能上的下降。
本地管理表空间正是为了解决这一问题来的,在表空间的空间管理上,ORACLE将存储信息保存在表空间的头部的位图中,而不是保存在数据字典中。通过这样的方式,在分配回收空间的时候,表空间就可以独立的完成操作也不用与其它对象关系。
下面就让我们进入到本地管理表空间的内部,看看ORACLE是怎么实现这一工作的。
4 用Uniform方式的本地管理表空间
4.1 当uniform size值太小时
SQL> create tablespace demo32 datafile '/oradata/ltest/demo32.dbf' size 10m extent management local uniform size 32k;
ORA-03249: Uniform size for auto segment space managed tablespace should have at least 5 blocks
注意: 我实验环境block为8k, 所以uniform size至少为40k.
4.2 当storage参数中的initial为空时
SQL> create tablespace demo64 datafile '/oradata/ltest/demo64.dbf' size 10m extent management local uniform size 64k;
Tablespace created
SQL> select a.initial_extent / 1024 "INIT_EXTENT(K)",
2 a.next_extent / 1024 "NEXT_EXTENT(K)"
3 from user_tablespaces a
4 where a.tablespace_name = 'DEMO64';
INIT_EXTENT(K) NEXT_EXTENT(K)
-------------- --------------
64 64
SQL> create table demotab64(x number) tablespace demo64;
Table created
SQL> select a.table_name,
2 a.initial_extent / 1024 "INIT_EXTENT(K)",
3 a.next_extent / 1024 "NEXT_EXTENT(K)"
4 from user_tables a
5 where a.table_name = 'DEMOTAB64';
TABLE_NAME INIT_EXTENT(K) NEXT_EXTENT(K)
-------------------------- -------------- --------------
DEMOTAB64 64 64
注意: 建表时没有存储参数initial时, 初始化区与下一个区的大小都是64k, 与uniform size的大小一样的.
SQL> select a.bytes / 1024 "INIT_EXTENT(K)" from user_extents a where a.segment_name = 'DEMOTAB64' and a.extent_id = 0;
INIT_EXTENT(K)
--------------
64
SQL>
COUNT(*)
----------
1
注意: 在该段中, 产生一个区.
4.3 当initial < uniform size时
SQL> create table demotab64_1(x number) tablespace demo64 storage (initial 1K next 5k);
Table created
SQL> select a.table_name,
2 a.initial_extent / 1024 "INIT_EXTENT(K)",
3 a.next_extent / 1024 "NEXT_EXTENT(K)"
4 from user_tables a
5 where a.table_name = 'DEMOTAB64_1';
TABLE_NAME INIT_EXTENT(K) NEXT_EXTENT(K)
--------------------------- -------------- --------------
DEMOTAB64_1 16 64
注意: 此时INIT_EXTENT为16, 不是initial参数的1.
SQL> select a.bytes / 1024 "INIT_EXTENT(K)" from user_extents a where a.segment_name = 'DEMOTAB64_1' and a.extent_id = 0;
INIT_EXTENT(K)
--------------
64
SQL> select count(*) from user_extents where segment_name = 'DEMOTAB64_1';
COUNT(*)
----------
1
4.4 当initial > uniform size时
SQL> create table demotab64_200(x number) tablespace demo64 storage (initial 200K next 20k);
Table created
SQL> select a.table_name,
2 a.initial_extent / 1024 "INIT_EXTENT(K)",
3 a.next_extent / 1024 "NEXT_EXTENT(K)"
4 from user_tables a
5 where a.table_name = 'DEMOTAB64_200';
TABLE_NAME INIT_EXTENT(K) NEXT_EXTENT(K)
-------------------------- -------------- --------------
DEMOTAB64_200 200 64
注意: initial > uniform size时, 初始化区的大小initial的大小.
SQL> select a.bytes / 1024 "INIT_EXTENT(K)" from user_extents a where a.segment_name = 'DEMOTAB64_200' and a.extent_id = 0;
INIT_EXTENT(K)
--------------
64
SQL> select count(*) from user_extents where segment_name = 'DEMOTAB64_200';
COUNT(*)
----------
4
注意: 此时分配的区已经不是1个了, 是4个. 在这种情况下initial就有起做作用. 分配区的数量为: 取整(initial/uniform size) + 1
结论: 在uniform size时, initial不管为多少时, 这个段的每一个区大小都为uniform size的大小.
5 用autoallocate方式的本地管理表空间
5.1 当storage参数中的initial为空时
SQL> create tablespace demoa datafile '/oradata/ltest/demoa.dbf' size 10m extent management local autoallocate;
Tablespace created
SQL> select a.initial_extent / 1024 "INIT_EXTENT(K)",
2 a.next_extent / 1024 "NEXT_EXTENT(K)"
3 from user_tablespaces a
4 where a.tablespace_name = 'DEMOA';
INIT_EXTENT(K) NEXT_EXTENT(K)
-------------- --------------
64
SQL> create table demoatab(x number) tablespace demoa;
Table created
SQL> select a.table_name,
2 a.initial_extent / 1024 "INIT_EXTENT(K)",
3 a.next_extent / 1024 "NEXT_EXTENT(K)"
4 from user_tables a
5 where a.table_name = 'DEMOATAB';
TABLE_NAME INIT_EXTENT(K) NEXT_EXTENT(K)
------------------------- -------------- --------------
DEMOATAB 64
SQL> select count(*) from user_extents where segment_name = 'DEMOATAB';
COUNT(*)
----------
1
此后不断增加数据,可以发现:
SQL> select a.segment_name, a.bytes, a.blocks from user_extents a where a.segment_name = 'DEMOATAB';
SEGMENT_NA BYTES BLOCKS
---------- ---------- ----------
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 65536 8
DEMOATAB 1048576 128
DEMOATAB 1048576 128
DEMOATAB 1048576 128
DEMOATAB 1048576 128
DEMOATAB 1048576 128
DEMOATAB 1048576 128
DEMOATAB 1048576 128
23 rows selected
当自动分配时,发现开始第一个区分配8个块(64K), 到17区开始, 每个区分配128个块(大小1M). 我做过实验当initial足够大时, 第一个区的大小不一定都是64K, 可以是1M, 8M, 64M 甚至是256M.
5.2 当initial < uniform size时
SQL> create table demoatab_1(x number) tablespace demoa storage (initial 1K next 5k);
Table created
SQL> select a.table_name,
2 a.initial_extent / 1024 "INIT_EXTENT(K)",
3 a.next_extent / 1024 "NEXT_EXTENT(K)"
4 from user_tables a
5 where a.table_name = 'DEMOATAB_1';
TABLE_NAME INIT_EXTENT(K) NEXT_EXTENT(K)
-------------------------- -------------- --------------
DEMOATAB_1 16
SQL> select a.bytes / 1024 "INIT_EXTENT(K)" from user_extents a where a.segment_name = 'DEMOATAB_1' and a.extent_id = 0;
INIT_EXTENT(K)
--------------
64
SQL> select count(*) from user_extents where segment_name = 'DEMOATAB_1';
COUNT(*)
----------
1
5.3 当initial > uniform size时
SQL> create table demoatab_200(x number) tablespace demoa storage (initial 200K next 5k);
Table created
SQL> select a.table_name,
2 a.initial_extent / 1024 "INIT_EXTENT(K)",
3 a.next_extent / 1024 "NEXT_EXTENT(K)"
4 from user_tables a
5 where a.table_name = 'DEMOATAB_200';
TABLE_NAME INIT_EXTENT(K) NEXT_EXTENT(K)
--------------------------- -------------- --------------
DEMOATAB_200 200
SQL> select a.bytes / 1024 "INIT_EXTENT(K)" from user_extents a where a.segment_name = 'DEMOATAB_1' and a.extent_id = 0;
INIT_EXTENT(K)
--------------
64
SQL> select count(*) from user_extents where segment_name = 'DEMOATAB_200';
COUNT(*)
----------
4
结论: 1. ORACLE通过强制性的手段使本地管理表空间中的所有Extent是同样大小的, 尽管可能自定义了不同的存储参数. 2. 在自动分配的本地管理的表空间中, 区间尺寸可能由以下尺寸组成64K, 1M, 8M, 64M 甚至是256M. 但是不管多大, 都有一个通用尺寸64k, 所以64K就是该表空间的位大小.
6 检查uet$与fet$是否有数据
SQL> select file#, name from v$datafile;
FILE# NAME----------------------------------------
1 /oradata/LTEST/datafile/o1_mf_system_79q5214w_.dbf
2 /oradata/LTEST/datafile/o1_mf_undotbs1_79q521ct_.dbf
3 /oradata/LTEST/datafile/o1_mf_sysaux_79q52169_.dbf
4 /oradata/LTEST/datafile/o1_mf_users_79q521do_.dbf
5 /oradata/LTEST/datafile/o1_mf_example_79q55jt4_.dbf
6 /oradata/LTEST/datafile/o1_mf_bigtbs_7ct5vw4x_.dbf
12 /oradata/ltest/demo64.dbf
13 /oradata/ltest/demo1024.dbf
14 /oradata/ltest/demoa.dbf
9 rows selected
可以检查uet$与fet$
SQL> select count(*) from uet$ where file# = 12;
COUNT(*)
----------
0
SQL> select count(*) from fet$ where file# = 12;
COUNT(*)
----------
0
采用本地管理的表空间, 这两张视图中没有数据. 下面就通过Dump块的信息, 来进一步分析本地管理表空间的特点.
7 Dump数据文件中位图信息(第3个块到第8个块)
7.1 dump第三个块
数据文件的前两个块是文件头, 所以dump第3个块. 从第3个块到第8个块是该数据文件的数据文件的位图区. 如果db_block_size为8192, 那么占用的空间为64K. http://blog.csdn.net/huang_xw/article/details/6966245文也用另一种不是很严谨的方法验证了占用64K大小的问题.
SQL> alter system dump datafile 12 block 3;
System altered
Dump出来的信息如下:
Start dump data blocks tsn: 13 file#: 12 minblk 3 maxblk 3
buffer tsn: 13 rdba: 0x03000003 (12/3)
scn: 0x0000.0011ee0d seq: 0x01 flg: 0x04 tail: 0xee0d1e01
frmt: 0x02 chkval: 0x430e type: 0x1e=KTFB Bitmapped File Space Bitmap
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00000000064EFC00 to 0x00000000064F1C00
0064EFC00 0000A21E 03000003 0011EE0D 04010000 [................]
0064EFC10 0000430E 0000000C 00000009 00000000 [.C..............]
0064EFC20 00000001 0000F7F7 00000000 00000000 [................]
0064EFC30 00000000 00000000 00000FF1 00000000 [................]
0064EFC40 00000000 00000000 00000000 00000000 [................]
Repeat 506 times
0064F1BF0 00000000 00000000 00000000 EE0D1E01 [................]
File Space Bitmap Block:
BitMap Control: 这句话说明该块还是位图区(3-8块都这样子, 可dump每个块出来验证)
RelFno: 12, BeginBlock: 9, Flag: 0, First: 1, Free: 63479
F10F000000000000 0000000000000000 0000000000000000 0000000000000000 (共248行)
0000000000000000 0000000000000000 0000000000000000 0000000000000000
……
0000000000000000 0000000000000000 0000000000000000 0000000000000000
End dump data blocks tsn: 13 file#: 12 minblk 3 maxblk 3
共248行, 每行32个字节, 每个字节8位, 共有位数: 248 * 32 * 8 = 63488
前面两节的内容是: F10F => 1111 0001 0000 1111 => 9个位为1, 与下面通过user_extents算出来的一样. 还有空闲区共有: 63488 - 9 = 63479 (注意: 位大小为1的个数与extent个数相等, 只是一个巧合. 因为位图管理中位大小为1对应的是8个block的使用情况, 当一个区的分配大小不为8个block时, 比如128个block时, 两者就不会相等了.)
可看表空间DEMO64中已经用了几个区.
SQL> select count(*) from user_extents a where a.tablespace_name = 'DEMO64';
COUNT(*)
----------
9
7.2 先扩展后, 再dump第三个块
SQL> alter table demotab64 allocate extent;
Table altered
SQL> alter system dump datafile 12 block 3;
System altered
Dump出来的信息如下:
Start dump data blocks tsn: 13 file#: 12 minblk 3 maxblk 3
buffer tsn: 13 rdba: 0x03000003 (12/3)
scn: 0x0000.0011fc4f seq: 0x01 flg: 0x00 tail: 0xfc4f1e01
frmt: 0x02 chkval: 0x0000 type: 0x1e=KTFB Bitmapped File Space Bitmap
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00000000064EFC00 to 0x00000000064F1C00
0064EFC00 0000A21E 03000003 0011FC4F 00010000 [........O.......]
0064EFC10 00000000 0000000C 00000009 00000000 [................]
0064EFC20 00000002 0000F7F6 00000000 00000000 [................]
0064EFC30 00000000 00000000 00000FF3 00000000 [................]
0064EFC40 00000000 00000000 00000000 00000000 [................]
Repeat 506 times
0064F1BF0 00000000 00000000 00000000 FC4F1E01 [..............O.]
File Space Bitmap Block:
BitMap Control:
RelFno: 12, BeginBlock: 9, Flag: 0, First: 2, Free: 63478
F30F000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
……
0000000000000000 0000000000000000 0000000000000000 0000000000000000
End dump data blocks tsn: 13 file#: 12 minblk 3 maxblk 3
前面两节的内容是: F30F => 1111 0011 0000 1111 => 10个位为1.
说明通过语句”alter table demotab64 allocate extent”, 又增加了一个区的分配.
8 Dump数据文件中数据信息(比如第9个块)
查看dba_extents视图, 也可以发现表DEMOTAB64从第9个块开始分配第一个区.
SQL> select a.segment_name, a.file_id, a.block_id, a.extent_id from dba_extents a where a.segment_name = 'DEMOTAB64';
SEGMENT_NAME FILE_ID BLOCK_ID EXTENT_ID
-------------- ---------- ---------- ----------
DEMOTAB64 12 9 0
DEMOTAB64 12 17 1
Dump第9个块, 这个块相当表头的信息.
SQL> alter system dump datafile 12 block 9;
System altered
Dump出来的信息如下:
Start dump data blocks tsn: 13 file#: 12 minblk 9 maxblk 9
buffer tsn: 13 rdba: 0x03000009 (12/9)
scn: 0x0000.0011fc4f seq: 0x02 flg: 0x04 tail: 0xfc4f2002
frmt: 0x02 chkval: 0x5aaf type: 0x20=FIRST LEVEL BITMAP BLOCK
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x00000000064EFC00 to 0x00000000064F1C00
0064EFC00 0000A220 03000009 0011FC4F 04020000 [ .......O.......]
0064EFC10 00005AAF 00000000 00000000 00000000 [.Z..............]
0064EFC20 00000000 00000000 00000000 00000000 [................]
Repeat 1 times
0064EFC40 00000000 00000000 00000000 00000004 [................]
0064EFC50 FFFFFFFF 0000000D 00000003 00000010 [................]
0064EFC60 00010002 00000000 00000000 00000000 [................]
0064EFC70 00000000 00000003 00000000 00000000 [................]
0064EFC80 00000000 00220008 000001C4 00000003 [......".........]
0064EFC90 0300000A 00000000 00000000 00000003 [................]
0064EFCA0 00000008 0300000C 00000000 00000000 [................]
0064EFCB0 00000000 00000000 00000000 00000001 [................]
0064EFCC0 0000CE6D 00000000 00000000 03000009 [m...............]
0064EFCD0 00000008 00000000 03000011 00000008 [................]
0064EFCE0 00000008 00000000 00000000 00000000 [................]
0064EFCF0 00000000 00000000 00000000 00000000 [................]
Repeat 8 times
0064EFD80 00000000 00000000 00000000 00001011 [................]
0064EFD90 00000000 00000000 00000000 00000000 [................]
Repeat 485 times
0064F1BF0 00000000 00000000 00000000 FC4F2002 [............. O.]
Dump of First Level Bitmap Block
--------------------------------
nbits : 4 nranges: 2 parent dba: 0x0300000a poffset: 0
unformatted: 13 total: 16 first useful block: 3
owning instance : 1
instance ownership changed at
Last successful Search
Freeness Status: nf1 0 nf2 0 nf3 0 nf4 0
Extent Map Block Offset: 4294967295
First free datablock : 3
Bitmap block lock opcode 3
Locker xid: : 0x0008.022.000001c4
Inc #: 0 Objd: 52845
HWM Flag: HWM Set
Highwater:: 0x0300000c ext#: 0 blk#: 3 ext size: 8
#blocks in seg. hdr's freelists: 0
#blocks below: 0
mapblk 0x00000000 offset: 0
--------------------------------------------------------
DBA Ranges :
--------------------------------------------------------
0x03000009 Length: 8 Offset: 0
0x03000011 Length: 8 Offset: 8
0:Metadata 1:Metadata 2:Metadata 3:unformatted
4:unformatted 5:unformatted 6:unformatted 7:unformatted
8:unformatted 9:unformatted 10:unformatted 11:unformatted
12:unformatted 13:unformatted 14:unformatted 15:unformatted
--------------------------------------------------------
End dump data blocks tsn: 13 file#: 12 minblk 9 maxblk 9
如果表空间存在多个数据文件,那么extent在扩展的时候是如何决定在那个extent文件分配空间的呢?
下面做一个试验来说明这个问题:
本实验以本地管理的表空间为例。
--建立系统管理的本地表空间
SQL> create tablespace tbs_system datafile 'E:ORACLEORADATAORACLE9Itbs_system01.dbf' size 2112k,'E:ORACLEORADATAORACLE9Itbs_system02.dbf' size 2112k,'E:ORACLEORADATAORACLE9Itbs_system03.dbf' size 2112k,'E:ORACLEORADATAORACLE9Itbs_system04.dbf' size 2112k;
Tablespace created
--建立统一尺寸的本地表空间
SQL> create tablespace tbs_uniform datafile 'E:ORACLEORADATAORACLE9Itbs_uniform01.dbf' size 2112k,'E:ORACLEORADATAORACLE9Itbs_uniform02.dbf' size 2112k,'E:ORACLEORADATAORACLE9Itbs_uniform03.dbf' size 2112k,'E:ORACLEORADATAORACLE9Itbs_uniform04.dbf' size 2112k uniform size 64k;
Tablespace created
--建立一个基于系统管理表空间的表
SQL> create table t_system tablespace tbs_system as select * from item where rownum<15000;
Table created
SQL> select extent_id,blocks ,file_id from dba_extents where segment_name='T_SYSTEM';
EXTENT_ID BLOCKS FILE_ID
---------- ---------- ----------
0 8 10
1 8 10
2 8 10
3 8 10
4 8 10
5 8 10
6 8 10
7 8 10
8 8 10
9 8 10
10 8 10
11 8 10
12 8 10
13 8 10
14 8 10
15 8 10
16 128 11
17 128 12
18 128 13
19 128 10
EXTENT_ID BLOCKS FILE_ID
---------- ---------- ----------
20 128 11
21 128 12
22 rows selected
--从查询结果可以看出,在前16个extent前(每个extent大小是64k),extent都在同一个数据文件中;从17个extent(1m)开始,extent在同一个表空间的数据文件中循环分配。
--建立基于统一尺寸本地表空间的表
SQL> create table t_uniform tablespace tbs_uniform as select * from item where rownum<15000;
Table created
SQL> select extent_id,blocks ,file_id from dba_extents where segment_name='T_UNIFORM';
EXTENT_ID BLOCKS FILE_ID
---------- ---------- ----------
0 8 14
1 8 15
2 8 16
3 8 17
4 8 14
5 8 15
6 8 16
7 8 17
8 8 14
9 8 15
10 8 16
11 8 17
12 8 14
13 8 15
14 8 16
15 8 17
16 8 14
17 8 15
18 8 16
19 8 17
EXTENT_ID BLOCKS FILE_ID
---------- ---------- ----------
20 8 14
21 8 15
22 8 16
23 8 17
24 8 14
25 8 15
26 8 16
27 8 17
28 8 14
29 8 15
30 8 16
31 8 17
32 8 14
33 8 15
34 8 16
35 8 17
36 8 14
37 8 15
38 8 16
39 8 17
40 8 14
--从以上查询结果可以看出,在统一尺寸的表空间下,extent从一开始就在同一表空间下的各个数据文件中循环扩展。
经过测试,在DMT下,oracle在数据文件中扩展extent时也是趋于循环的。
我们可以利用oracle的这一特性,不用分区、不用在操作系统级做条带化,只需要在建立表空间时多添加几个数据文件(各个数据文件位于不同的磁盘中),就可以实现简单的条带化。
总结:
如果一个表空间存在多个数据文件,且多个数据文件都有可用的空间,则
1、如果是系统管理的本地表空间,为了使所有小区在一起,以避免在需要文件中分配大量小区而导致在删除对象时而产生的碎片,oracle会把对象的前16个extent(64k)都分配在同一个数据文件中;从第17个extent开始才循环在同一个表空间的各个数据文件中扩展。
2、如果是统一尺寸的本地管理表空间,则不用担心碎片问题,extent从一开始就在多个数据文件中循环分配。