ORACLE 10G中,对于空间的回收利用已经有了很大的提高,这里讨论的只限于在线系统的空间回收,而对于应用可以停的回收方法,比如CTAS然后TRUNCATE原表,然后再把表RENAME回来这样类似的方法不做讨论。对于但表的回收技巧,比如MOVE、SHRINK等也不错过多的描述,只需要提醒大家注意的是MOVE会锁表,所以在线系统请谨慎使用,而且MOVE后,表上相关的索引会失效。虽然表的MOVE有ONLINE选项可以使用,但这个ONLINE只能用在IOT的表上,而普通表不能使用。另外使用SHRINK的时候,表的第一个EXTENT很重要,如果这个EXTENT在数据文件中的位置很靠后,那SHRINK后,数据文件还是没有办法进行缩小的,空间还是收不回来。(这些未经完全测试,使用前请注意测试)
[@more@]这里主要讨论的是分区表中的分区移动来实现数据空间的回收。几个表空间,因为当初数据量很大,所表几个表空间都曾经膨胀了很大,但是经过历史数据清理后(删除一些表和分区),这些表空间很空闲,但是因为很多EXTENT的BLOCKID很靠后,所以空间收不回来,而且这些表空间中的数据表都是分区表,而且都是已经过期,目前基本不会用到的分区表,只会有查询统计发生在这些表上,那么,就可以使用把某些表空间中的表分区移动到其他表空间,从而把这个表空间腾空,另一个表空间充满,最后回收空的表空间来达到缩小整体空间使用的目的。
MOVE分区表可能会导致全局索引或者分区索引失效,那么会影响到在线事务的进行,不过ORACLE提供了UPDATE INDEXES的关键字来使得MOVE PARTITION的时候,相关的索引也进行相应的更新,从而避免对在线事务的影响。下面来看看这些语法:
简单的把一个分区移动到另一个表空间,同时UPDATE INDEXES关键字指定了更新表上所有的索引(包括GLOBAL和LOCAL)
alter table tab move partition p_tab tablespace tbl update indexes;
如果只更新GLOBAL索引:
alter table tab move partition p_tab tablespace tbl update global indexes;
如果更新索引的同时改变索引的存放位置:
alter table tab move partition p_tab tablespace tbl update indexes (idx_tab (partition p_idx_tab tablespace tbl));
如果更新的分区中包含LOB字段,则LOB字段可以单独的MOVE,或者随分区表一起MOVE:
alter table tab move partition p_tab tablespace tbl lob (tab.lob_colname) store as lobname (tablespace tbl);
只移动LOB的存放位置:
alter table tab move partition p_tab lob (tab.lob_colname) store as lobname (tablespace tbl);
其中如果LOBNAME不指定,则使用原先的LOBNAME(也就是LOB SEGMENT的PARTITION NAME);如果不带LOB的属性,只进行分区的移动,则LOB不会跟随表分区进行移动。
并且,可以只移动一个子分区而不是整个分区,只需要把上面的PARTITION关键字换成SUBPARTITION即可。指定表空间位置只是这里用到的一个MOVE相关的属性,其实表和索引相关的存储属性,比如PCT值、初始事务数的值、是否压缩等等都是可以在MOVE中实现的。需要注意的就是MOVE的时候加上UPDATE INDEXES关键字虽然不会使得索引失效,但是移动数据量很大的时候会产生很多日志,而且比较耗费资源,最重要的是会在整个分区上加一个独占锁,从而导致这个分区上出了SELECT外的其他DML都被阻塞,因此如果要避免MOVE当前使用的分区。
最后,MOVE分区表会有两个相关的BUG,一个是HASH分区包含LOB的字段进行LOB分区MOVE的时候会报一个ORA-22877错(BUG:4583442 );另一个是MOVE分区后,可能会导致数据字典表IND$中的LOB索引不会被更新,从而使得之后删除这个表空间的时候报一个ORA-22864的错(BUG:4748597 )。这两个BUG相关的链接如下:
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25016/viewspace-1016566/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/25016/viewspace-1016566/