Oracle通过表空间为数据库提供使用空间,那么Oracle必然提供一种技术用于空间管理。
Oracle主要的空间管理方式有两种,一种是Oracle 8i以前的字典管理表空间(DMT)技术,一种就是Oracle 8i以后的本地管理表空间(LMT)技术。由于区间(Extent)是Oracle创建对象时的最小分配单元,所以表空间的管理实际上就是针对于区间的管理。
一.字典管理表空间
在Oracle 8i以前(不包括8i),只存在一种表空间的管理模式,这就是字典管理表空间(Dictionary Managed Tablespace,简称DMT)。之前创建表空间的主要语法为:
CREATE TABLESPACE tablespace_name
DATAFILE 'datafile_path_name' [SIZE INTETER [K|M]
|[DEFAULT STORAGE]|[PERMANENT|TEMPORARY]]
这里关键字DEFAULT STORAGE指明了该表空间的默认存储格式,包含了INITIAL、NEXT、PCTINCREASE等相关参数的设置。如果在表空间中创建对象(如表、索引等)时不指定存储参数的话,Oracle将采用表空间的存储参数作为对象的默认参数;PERMANENT|TEMPORARY指明了该表空间的类型是永久的还是临时的。
当表空间被创建之后,可以通过查询dba_tablespaces视图来确定表空间的类型:
SQL> select tablespace_name, extent_management,allocation_type
2 from dba_tablespaces;
TABLESPACE_NAME EXTENT_MAN ALLOCATIO
------------------------------ ---------- ---------
SYSTEM DICTIONARY USER
RBS DICTIONARY USER
TEMP DICTIONARY USER
USERS LOCAL UNIFORM
4 rows selected.
EXTENT_MANAGEMENT显示为DICTIONARY的就是字典管理表空间。所谓字典管理表空间是指,当创建或删除对象时,Oracle的空间分配或回收是通过数据库中的数据字典表来记录和管理的,用于管理的两个数据字典表分别是:UET$(Used Extents,已使用的空间)和FET$(Free Extents,空闲空间)。
可以来简单看一下这两个字典表的结构:
SQL> desc uet$
名称 空? 类型
----------------------------------------- -------- ----------------------------
SEGFILE# NOT NULL NUMBER
SEGBLOCK# NOT NULL NUMBER
EXT# NOT NULL NUMBER
TS# NOT NULL NUMBER
FILE# NOT NULL NUMBER
BLOCK# NOT NULL NUMBER
LENGTH NOT NULL NUMBER
SQL> desc fet$
名称 空? 类型
----------------------------------------- -------- ----------------------------
TS# NOT NULL NUMBER
FILE# NOT NULL NUMBER
BLOCK# NOT NULL NUMBER
LENGTH NOT NULL NUMBER
可以清晰地看到,这两个字典表基本上是通过文件号(file#)、数据块号(block#)等信息来管理空间的分配和回收的。
字典管理表空间的工作方式是--当建立一个新的段或者段在表空间中请求新的空间时,Oracle通过执行一系列的SQL语句来完成这个工作,这些工作包括从FET$中找到可用的自由空间,移动或增加相应的行到UET$中,并在FET$中删除相应的记录;当删除一个段的时候,Oracle则移动UET$中相应的行到FET$。
这个过程的发生是连续的、串行的,在繁忙的数据库中,这类操作极可能导致竞争和等待,产生数据字典的争用;另一方面,当数据字典的表的信息被修改时,系统同样要记录undo和redo信息,频繁的修改又不可避免地对整个数据库的性能产生影响。
在繁忙的数据库中,字典管理的表空间可能会成为灾难,下面展示一段Statspack报告,在这个采样周期为1小时的报告中:
DB Name DB Id Instance Inst Num Release OPS Host
------------ ----------- ------------ -------- ----------- --- ------------
TEAM 2757346 ss7 1 8.1.7.4.0 NO db-server
Snap Id Snap Time Sessions
------- ------------------ --------
Begin Snap: 2716 28-10月-03 08:15:03 20
End Snap: 2718 28-10月-03 09:15:31 20
Elapsed: 60.47 (mins)
注意到在根据Buffer Gets排序的Top SQL中,有大量的SQL是在进行字典表的空间维护操作,这已经成为了这个数据库的性能瓶颈,下面报告中的SQL语句很好地展示了字典管理表空间的空间维护方式:
Buffer Gets Executions Gets per Exec % Total Hash Value
--------------- ------------ -------------- ------- ------------
4,800,073 10,268 467.5 51.0 2913840444
select length from fet$ where file#=:1 and block#=:2 and ts#=:3
803,187 10,223 78.6 8.5 528349613
delete from uet$ where ts#=:1 and segfile#=:2 and segblock#=:3 a
nd ext#=:4
454,444 10,300 44.1 4.8 1839874543
select file#,block#,length from uet$ where ts#=:1 and segfile#=:
2 and segblock#=:3 and ext#=:4
23,110 10,230 2.3 0.2 3230982141
insert into fet$ (file#,block#,ts#,length) values (:1,:2,:3,:4)
21,201 347 61.1 0.2 1705880752
select file# from file$ where ts#=:1
9,505 12 792.1 0.1 1714733582
select f.file#, f.block#, f.ts#, f.length from fet$ f, ts$ t whe
re t.ts#=f.ts# and t.dflextpct!=0 and t.bitmapped=0