DBA_EXTENTS视图记录了Segment中区的分配情况,可以通过查询这个视图获得数据库中每个区的分配情况:SQL> select segment_name,file_id,extent_id,block_id,blocks
2 from dba_extents where segment_name='OBJ$';
SEGMENT_NAME FILE_ID EXTENT_ID BLOCK_ID BLOCKS
-------------------- ---------- ---------- ---------- ----------
OBJ$ 1 0 121 8
OBJ$ 1 1 5241 8
OBJ$ 1 2 5721 8
OBJ$ 1 3 5857 8
OBJ$ 1 4 6281 8
OBJ$ 1 5 6953 8
OBJ$ 1 6 9209 8
OBJ$ 1 7 11681 8
OBJ$ 1 8 12801 8
OBJ$ 1 9 14713 8
OBJ$ 1 10 17009 8
OBJ$ 1 11 24889 8
OBJ$ 1 12 25081 8
OBJ$ 1 13 26961 8
OBJ$ 1 14 27425 8
OBJ$ 1 15 29553 8
OBJ$ 1 16 30729 128
17 rows selected.
如前文曾经介绍过的,我们可以通过这个视图观察本地管理表空间的空间分配规律(AUTOALLOCATE和UNIFORM SIZE)。作为DBA经常会面对的一个问题是,调整数据文件的大小,通常调整文件大小的命令如下:Alter database datafile ‘’ resize [size];
如果是扩大一个文件,那么通常只要空间足够并且未超过操作系统的限制,是很简单的,但是如果需要收缩一个文件,可能大家经常会遇到如下一个提示:SQL> alter database datafile '/opt/oracle/oradata/eygle/undotbs01.dbf' resize 100M;
alter database datafile '/opt/oracle/oradata/eygle/undotbs01.dbf' resize 100M
*
ERROR at line 1:
ORA-03297: file contains used data beyond requested RESIZE value
这个提示的意思是,在指定收缩的100MB之外,还存有数据,这样就不能够Resize到指定的大小。那么如何判断一个文件实际使用空间的大小呢?
通过dba_extents视图,可以做到精确判断,由于段的空间分配是以区为单位进行的,所以只要找到一个数据文件上最后一个区间占用的位置,就可以计算出一个数据文件的HWM。图5-10简要说明了一个数据文件的空间示意。
这和段空间的使用和收缩非常类似,可以通过如下SQL来确定不同文件可以进行收缩的空间:SQL> col name for a40
SQL> col resizecmd for a80
SQL> select a.file#,
2 a.name,
3 a.bytes / 1024 / 1024 CurrentMB,
4 ceil(HWM * a.block_size) / 1024 / 1024 ResizeTo,
5 (a.bytes - HWM * a.block_size) / 1024 / 1024 ReleaseMB,
6 'alter database datafile ''' || a.name || ''' resize ' ||
7 ceil(HWM * a.block_size) / 1024 / 1024 || 'M;' ResizeCmd
8 from v$datafile a,
9 (SELECT file_id, MAX(block_id + blocks - 1) HWM
10 FROM DBA_EXTENTS
11 GROUP BY file_id) b
12 where a.file# = b.file_id(+)
13 And (a.bytes - HWM * a.block_size) >0
14 order by 5
15 /
FILE# NAME CURRENTMB RESIZETO RELEASEMB
---------- ---------------------------------------- ---------- ---------- ----------
RESIZECMD
--------------------------------------------------------------------------------
1 /opt/oracle/oradata/eygle/system01.dbf 211.070313 211.0625 .0078125
alter database datafile '/opt/oracle/oradata/eygle/system01.dbf' resize 212M;
2 /opt/oracle/oradata/eygle/undotbs01.dbf 125 120.0625 4.9375
alter database datafile '/opt/oracle/oradata/eygle/undotbs01.dbf' resize 121M;
4 /opt/oracle/oradata/eygle/users.dbf 10 1.125 8.875
alter database datafile '/opt/oracle/oradata/eygle/users.dbf' resize 2M;
现在就可以根据查询结果进行数据文件的收缩:SQL> alter database datafile '/opt/oracle/oradata/eygle/undotbs01.dbf' resize 121M;
Database altered.
当然Resize对于文件中间的自由空间无能为力,为了释放更多的空间,可以尝试将文件末尾的对象移走,以使得自由空间调整到文件末尾,从而可以通过Resize释放这些空间,这非常类似于操作系统的空间整理与分区调整。通过以下SQL可以简单地查询出每个数据文件最末端存储的对象:SQL> col segment_name for a30
SQL> col semgent_type for a20
SQL> select /*+ rule */ owner,segment_name,segment_type from dba_extents
2 where (file_id,block_id) in
3 (select file_id,max(block_id) from dba_extents group by file_id);
OWNER SEGMENT_NAME SEGMENT_TYPE
------------------------------ ------------------------------ ------------------
SYS I_H_OBJ#_COL# INDEX
SYS _SYSSMU7$ TYPE2 UNDO
SYS ALERT_QT TABLE
EYGLE EYGLE TABLE
BOSSMGR SMS_ORG_HS_MO_0609 TABLE
DBMON DBA_IOEXTEND_DAY TABLE
6 rows selected