系统环境
硬件
方正圆明服务器
M的内存
硬盘有二个分区CD光驱为E
软件
操作系统WINDOWS SERVER
数据库ORACLE for NT
数据库
创建数据库后手工创建了二个表空间在存储管理器中查看其属性如下
TS_PAY M (initial size k next size k increase size %)
TS_IDX M (initial size k next size k increase size %)
操作
运行创建数据表索引触发器及其视图的脚本后TS_PAY占用MTS_IDX占用M
分三次录入相应的数据其中建立在表空间TS_PAY的数据表的数据量为M 建立在表空间TS_IDX的数据表的数据量为M
每次录入数据后用Oracle的实用工具Export以用户模式导出整个数据其他参数为默认值(导出的文件大小为M)其中在中途用Oracle的实用工具Import作过几次数据导入
现象
在OEM的存储管理中查看表空间的使用情况发现TS_PAY占用MTS_IDX占用M对几个占用空间圈较大的表和索引作了查询发现其数据的记录数据为但其占用空间由初建时的M变为M
录入的记录数只有十几条而且每条记录的占用空间也不大所以表空间的这种占用速度与表的数据量增长呈现出的比例是极度不正常的
原因分析
经过实际测试发现上述现象的产生是由于在导出时使用了参数COMPRESS = Y
在实用工具Export中参数Compress的缺省值为Y参数Compress指定Export和Import如何管理表数据的初始区
如果缺省的COMPRESS = Y则Export对表数据加标记以便在导入时合并到某个初始区也就是说参数COMPRESS = Y告诉ORACLE合计一个表中所有已分配的空间并且为了反映当前总的已分配空间在导出转储文件中修改了表创建语句的初始值初始区值是导出执行前表中所有已分配空间的总和
我们假设某个表有 个分区你想压缩它五个分区中的每一个都分配了(PCTINCREASE=)在每个分区中只有个字节是有数据的并且在最后一个区中没有已用的字节即空闲字节当使用参数COMPRESS=Y时ORACLE简单地累加了所有已分配的空间然后分配字节作为导出转储文件中CREATE TABLE语句的初始区值这样当你执行操作后ORACLE将把数据放在表区最初的大约字节中将近个字节的空间是空闲的
如果指定COMPRESS = NExport将使用当前存储参数包括初始区和下一个区的大小值参数值可能是在CREATE TABLE或ALTER TABLE语句中指定的值也可能是数据库系修改过的值例如如果表增大而且如果PCTINCREASE参数不为零NEXT区的大小值就可能被修改
虽然实际的合并是在导入时执行的但是只能在导出时而不能在导入时指定COMPRESS参数是Export实用程序而不是Import实用程序生成数据定义包括存储参数定义这样如果在导出时指定COMPRESS = Y就只能以合并形式导入数据COMPRESS参数不压缩LOB数据对于LOB数据使用初始区大小和下一区大小的原始值
解决办法
没有进行过导出导入操作或没有做过导入参数为COMPRESS=Y的数据
这时只需在导出数据时选择参数COMPRESS的值为N就不会出现上述现象
如果数据已经以COMPRESS = Y方式导出而且又被Import实用工具导入或数据库中的数据损坏只有用导出的数据导入
这种情况的处理较为复杂一点可以分为以下几个步骤来做
()对于几个占用空间较大的数据表分别创建中间临时表例如对于表SBYY我们可以进行如下操作
CREATE TABLE T_TMP AS SELECT * FROM SBYY
()删除数据库中的表SBYY
DROP TABLE SBYY
()在数据库中按原结构重建表SBYY
CREATE TABLE SBYY(
JLDW_DMchar()NOT NULL
JLDW_MCvarchar() NOT NULL
JLDW_JCvarchar() NOT NULL
XYBZ char()NOT NULL
CONSTRAINT PK_SB_DM_JLDW_CKHW PRIMARY KEY (JLDW_DM)
);
()将临时表T_TMP中的数据插入到重建的表SBYY中
INSERT INTO SBYY SELECT * FROM T_TMP
()删除临时表T_TMP
DROP TABLE T_TMP;
对于其它数据量不大但占空间较大的表或索引依次进行如上五个步骤的处理即可
注意这种方法对于表间关系不复杂的数据清理比较简便而有用对于关联较复杂的表及其索引等要进行仔细分析表间关系才可动手