通过前面两节学习可知,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

 

先获取该SESSIONSID,方便实验观察

 

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命令可以释放空间(当然这语句最根本的作用还是移动表到不同的表空间去,这里只是借用它可以释放空间的一个特性),还要了解该动作会锁表直到命令结束,而且会导致索引失效,属于危险命令,建议千万不要在业务高峰期操作。