参考文章:
http://www.2cto.com/database/201201/117275.html
http://blog.csdn.net/huangchao_sky/article/details/8700394
http://www.2cto.com/database/201201/117816.html
http://www.cnblogs.com/Cratical/archive/2010/08/24/1806948.html
切记:
move操作会锁表。
如果是很小的表,可以在线做。
如果是大表一定要注意,会长时间锁表,只能查询,影响正常业务运行。
move操作会使索引失效,一定要rebuild。
(在这方面吃过亏,所以记得很清楚。)
shrink操作期间可以对表进行增删改查。
简单总结对比
alter table table_name move和alter table table_name shrink space都可以用来收缩段,消除部分行迁移(Row Migration) 消除空间碎片,使数据更紧密,降低高水位HWM。
但是有如下区别:
- 使用alter table move,会把表格最多收缩到创建表格时的storage子句指定的初始大小,使用alter table shrink space,则不受此限制。
(也就是说,如果创建表的DDL语句指明了初始大小为10M,数据量最大时占用15M,假定现在表的数据只占用了2M,那么move操作只能将表占用空间减小到10M,HWM为2M。而shrink可以将表的空间占用和HWM都降到2M。)
(如果想是用move的方式收缩到初始化大小以下,需要在alter move语句中加初始化参数。) - 使用alter table move之后,索引会无效,需要重建,因为move操作会改变一些记录的ROWID,所以MOVE之后索引会变为无效,需要REBUILD。使用alter table shrink space,则不会使索引无效,因为使用shrink space时,索引会自动维护。
- 只能在表格所在的表空间是自动段空间管理(创建tablespace时指定了SEGMENT SPACE MANAGEMENT AUTO子句)的时候,才能使用alter table shrink space。
- 如果在业务繁忙时做压缩,可以使用alter table shrink space compact来对表格进行碎片整理,而不调整HWM,之后再次调用alter table shrink space来释放空间。
- 可以使用alter table shrink space cascade来同时对索引都进行收缩,这等同于同时执行alter index shrink space。
- alter table t move和alter table t shrink space都可以用来消除行链接(Row Chaining)和行迁移(Row Migration)。
为此需要先建立chained_rows表格。
首先执行$ORACLE_HOME/RDBMS/ADMIN/utlchain.sql脚本建立chained_rows表格,
然后执行analyze table xxx list chained rows [into chained_rows],如果存在行链接或者行迁移,查询chained_rows就能找到发生了行链接或者行迁移的行。
然后执行alter table move或shrink space,然后再次查看chained_rows表即可验证行链接是否消失。
下面做实验验证一下:
第一个区别
drop table TEST_MOVE;
CREATE TABLE TEST_MOVE
(IP VARCHAR2(30 BYTE),
CHECKDATE VARCHAR2(30 BYTE),
CMDTYPE VARCHAR2(50 BYTE),
CONFIGDETAIL VARCHAR2(500 BYTE)
) SEGMENT CREATION IMMEDIATE
STORAGE(INITIAL 10485760 NEXT 1048576)
TABLESPACE USERS;
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST_MOVE';
SEGMENT_NAME EXTENTS BLOCKS INIT
------------------------------ ---------- ---------- ----------
TEST_MOVE 3 1280 10
--TEST表初始分配了10M的空间,可以看到有10个EXTENTS,1280个BLOCKS。USER_TABLES视图显示有0个使用的BLOCKS,1280个空闲BLOCKS,即该10M空间内的BLOCK都还没被ORACLE”格式化”。
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST_MOVE';
TABLE_NAME BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ------------
TEST_MOVE
--向表中插入数据
SQL> insert into TEST_MOVE select * from information;
122513 rows created.
SQL> analyze table TEST_MOVE compute statistics;
Table analyzed.
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST_MOVE';
SEGMENT_NAME EXTENTS BLOCKS INIT
------------------------------ ---------- ---------- ----------
TEST_MOVE 3 1280 10
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST_MOVE';
TABLE_NAME BLOCKS EMPTY_BLOCKS
------------------------------ ---------- ------------
TEST_MOVE 1006 274
--插入数据后,分配的空间仍不变,因为10个EXTENTS还没使用完。显示使用了1006个BLOCKS,空闲274个BLOCKS。这时候的1006 BLOCKS即是高水位线。
SQL> commit;
Commit complete.
SQL> select count(*) from test_move;
COUNT(*)
----------
122513
SQL> delete from test_move where rownum<=