通过前面两节学习可知,deltete不会释放表空间,但是可以重用,也就是插入可以填补空洞,当然现实应用中确实是存在经常删除很少插入的情况,这样就存在了释放表空间优化数据库的可行性了,truncate有不能带条件的缺陷,自然就想到用alter table move重移表空间的方法。这里要注意三个要素 1、 alter table move 省略了tablespace XXX, 表示用户移到自己默认的表空间,因此当前表空间至少要是该表两倍大,这很好理解,由于易错所以提出,就不再细说了。 2、 alter table move过程中会导致索引失效,必须要考虑重新索引 3、 alter table move过程中会产生锁,应该避免在业务高峰期操作! 就第二点和第三点做实验说明如下吧 Connected to Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 Connected as ljb 先获取该SESSION的SID,方便实验观察 SQL> select sid from v$mystat where rownum=1; SID -------------------- 160 SQL> create table ljb_test as select * from dba_objects; Table created SQL> select count(*) from ljb_test; COUNT(*) ------------------- 62659 SQL> create index idx_test on ljb_test(object_id); Index created 查询当前该SESSION并无锁 SQL> select * from v$lock where sid=160; ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ----------------------------------------- 查看索引状态也正常! SQL> select index_name,table_name,status from user_indexes where table_name='LJB_TEST'; INDEX_NAME TABLE_NAME STATUS ------------------------------ ------------------------------ ----------------------------------------------- IDX_TEST LJB_TEST VALID alter table ljb_test move; 重新再开一个窗口 执行如下命令,发现锁已经产生了 select * from v$lock where sid=160; ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ------ ---- ------- ---------- ------ -------- ------ ------------------------------------------------------------------ 2043451C 20434530 160 CF 0 0 4 0 0 0 1FA072BC 1FA073D8 160 TX 917534 592 6 0 1 0 204344C0 204344D4 160 HW 76 323783147 6 0 0 0 1F9C4224 1F9C423C 160 TM 84825 0 6 0 0 0 204342F4 20434308 160 TT 76 16 4 0 0 0 1F9C377C 1F9C37C4 160 TS 76 323783147 6 0 0 0 不过由于alter table move命令未结束,索引仍然有效! SQL> select index_name,table_name,status from user_indexes where table_name='LJB_TEST'; INDEX_NAME TABLE_NAME STATUS ------------------------------ ------------------------------ ---------------------------------------------------- IDX_TEST LJB_TEST VALID 等alter table ljb_test move;命令结束后,再查看发现锁消失了 SQL> select * from v$lock where sid=160; ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK -------- -------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ------------------------------------------ 但是索引却失效了! SQL> select index_name,table_name,status from user_indexes where table_name='LJB_TEST'; INDEX_NAME TABLE_NAME STATUS ------------------------------ ------------------------------ ---------------------------------------------------- IDX_TEST LJB_TEST UNUSABLE 总结:这个实验说明:除了知道alter table move命令可以释放空间(当然这语句最根本的作用还是移动表到不同的表空间去,这里只是借用它可以释放空间的一个特性),还要了解该动作会锁表直到命令结束,而且会导致索引失效,属于危险命令,建议千万不要在业务高峰期操作。 |
|