在过去释放空间的办法中是一直使用调用存储过程(通过delete删除部分数据后)释放空间 ,但是空间一直无法释放的实际状况下(在oracle 数据库中表是由一个或多个extents组成,每增加或扩展一个extent,高水位标志(hwm)朝上上移动一个高位,其以下的空间就是数据空间的容量.当delete操作时,只是把数据删除,而并不能让这个hwm下降。所以空间一直无法释放)。在此种特殊的情况下,为了在72数据库上释放空间 必须重整空间,进而释放空间,来达到有效利用空间的目的。
第一 强烈建议升级数据(把现有的oracle 9i 升级到oracle 10g)升级方法有以下两种:
A:利用oracle提供的一个升级实用程序dbua(database upgrade assistant)直接将9i的数据库升级到10g
B:新建一个10g的数据库,利用oracle的导入/导出(imp/exp)实用程序迁移数据
对以上两种方法的比较
| 方法 | 范围 | 优点 | 缺点 | ||||
A | 第一 在原来装有oracle 9i的os上安装oracle 10g的软件(不需要安装10g的数据库) 第二 通过运10g的数据库升级助手实用程序dbua来完成oracle 9i到oracle 10g的升级过程 | 数据量比较大的情况下 | 第一 升级速度迅速 第二 保留原有数据库的物理结构(用户系统权限,表空间等),不用再次规划数据库的逻辑和物理结构 | 升级一旦失败,原来数据库会损坏,所以在升级前必须在测试环境下做好测试准备工作,以此来防备在正式的升级过程中出现的意外 | ||||
B | 第一 首先把oracle9i的数据库的数据导出(exp)出来 第二 然后安装一个oracle 10g的数据库,把导出的数据导入(imp)到新 oracle 10g的数据库中 | 数据量不是很大的情况下 | 第一 数据不会丢失,数据始终是安全存储的 第二 没有升级的风险 | 第一 导入导出的时间漫长 第二 重新规划数据库的物理和逻辑结构(数据库,数据文件,表空间等) |
第二 使用oracle 10g 的 shrink的新特性(联机段空间回收(shrinking database segments online))来重整表空间
联机段收缩仅对自动段空间管理(assm)表空间中的表有效,shringk的实质就是对表执行一系列的dml操作,对于表的末端找到的 ,就删除它们,并在表的顶端重新插入。通过这样的操作后,可以填满表段中的空闲空间,而把表的剩余空间保留在表的末端,随后oracle可以重置该表的高水位标志位(hwm),以此来释放自由的空间。但是由于段空间重整是通过dml操作来完成的,所以会额外滋生出大量的redo表空间
Alter table table_name enable row movement;
Alter table table_name shrink space;
第三 使用定时导出导入数据
A 依然利用已有的存储过程定期删除不需要的数据
B 通过使用 oracle 数据库所在的os 利用shelll脚本定时导出指定某张表的数据(已经有定时导出表数据的shell脚本)
C 利用oracle 的 job条用存储过程来彻底truncate表
D 再利用oracle 数据库所在的os shell脚本导入truncate后的表
以上三步是彻底重整表空间,让hwm重置,达到快速释放表空间。这样也杜绝了使用delete无法释放表空间的目的。
第四 联机重定义表(online redofine table)
A 移动需要调整的表到相同 Schema 下的 不同表空间内,以此来释放delete后的空闲空间
1. 验证该表是否可以进行联机重定义(如果不可以会给出具体原因):
exec DBMS_REDEFINITION.can_REDEF_TABLE(''schema'',''tablename'',1);
2. 创建中间临时表:
Create table tablename as select * from tablename_old(被验证的联机重定义表)
3. 定义表
BEGIN
DBMS_REDEFINITION.start_redef_table
('' schema '',''table'',''tablename_old'',
''tablename的字段 tablename_old的字段,
……
'',
DBMS_REDEFINITION.cons_use_rowid(pk)
);
END;
4. 创建索引限制以及触发器等
DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS()
ALTER TABLE tablename_old
ADD CONSTRAINT index_name PRIMARY KEY (ID)
USING INDEX
TABLESPACE tablespace_name;
5. 同步表数据内容并建立物化视图
EXEC DBMS_REDEFINITION.sync_interim_table (''schema'', ''tablename'', ''tablename_old'');
6. 结束重定义过程
EXEC DBMS_REDEFINITION.finish_redef_table (''schema'', ''tablename'', ''tablename_old'');
7. 删除表
Drop table tablename_old;
注: 如果想中途停止重定义过程,则通过如下指令退出该过程:
EXEC dbms_redefinition.abort_redef_table(“schema”, “tablename”,”tablename_old”);
B 重建表以便减少碎片,通过减少碎片来充分空闲空间
1. 查看表空间碎片超过30%的schema
select * from (
Select owner,table_name,(num_rows*avg_row_len/8000),blocks,
(num_rows*avg_row_len/8000)/( decode(blocks,0,1,null,1,blocks)) bb
from dba_tables where owner in ('schema') and TEMPORARY='N') tt
where tt.bb<0.7 and blocks>10;
2. 通过rename具体的的table,然后在创建表,最后插入rename后的表的数据,以此来彻底释放表的空闲空间
第五 使用rename+insert的组合来释放表的空闲空间
对于实时使用的数据库表,我们的业务类型主要是属于以写为主,也就是说是不断的往表中insert数据。可以通过rename将表更名,然后按原来的结构重建表,此时插入的数据可以恢复,同事该过程的操作非常的迅速,对数据库影响很小。随后可以将rename表总的数据插入回来。这样就完成了数据整理,从而hwm降低重置。从而释放了表的空闲空间。
第六 压缩以存在的分区表和表空间
压缩表可以使同样的数据占用更少的空间,它对空间的使用、性能的提高都有积极的作用,压缩表比没有压缩的表在全表扫描时,逻辑读明显减少了。对表进行了压缩后,表段占用的空间也小了。这些block被读到buffer时仍然是压缩的状态,所以这样可以减少数据库读取的IO,也可以认为压缩表相当于扩充了SGA,因为同样的数据用了更少的内存。一个压缩的表可以存储在更少的数据块中,从而节省了宝贵的存储空间,由此使用更少的数据块也意味着性能的提高。在i/o受到一定限制的环境中,对一个压缩的表进行查询通常是可以更快的完成,因为它读取的数据块少了。(目前在72db上的表空间和分区表都没有压缩)
A. 压缩一个已分区的表
对已分区的表进行压缩时有以下两种方法
a) 表级别上压缩(alter table table-name compress)
b) 分区级别上压缩(alter table partition_name move partition partition-value compress)
B. 使现有的表空间转化为压缩表空间
alter tablespace tablespace_name default compress;
以上各种的办法都是从空间重整这点出发,以此来释放空闲空间。让宝贵的磁盘空间能高效的利用。然而在这个过程中,其他的问题也有滋生的情况,比如redo表空间,undo表空间等都会相继的出现不足,所以在处理时。必须首先扩容这些空间的容量达到我们重整空间的目的。以上各个细节如有不足之处请指正,以便进一步的修正,更新。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/20976446/viewspace-674114/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/20976446/viewspace-674114/