oracle move 做了什么意思,alter table move跟shrink space的区别(转)
都知道alter table move 或shrink space可以收缩段,用来消除部分行迁移,消除空间碎片,使数据更紧密,但move 跟shrink space还是有区别的。Move会移动高水位,但不会释放申请的空间,是在高水位以下(below HWM)的操作。而shrink space 同样会移动高水位,但也会释放申请的空间,是在高水位上下(below and above HWM)都有的操作
都知道alter table move 或shrink space可以收缩段,用来消除部分行迁移,消除空间碎片,使数据更紧密,但move 跟shrink space还是有区别的。
Move会移动高水位,但不会释放申请的空间,是在高水位以下(below HWM)的操作。
而shrink space 同样会移动高水位,但也会释放申请的空间,是在高水位上下(below and above HWM)都有的操作。
也许很难理解吧,看测试就知道了。
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
SQL> create table test (id number) storage (initial 10m next 1m) tablespace users;
Table created.
SQL> analyze table test compute statistics;
Table analyzed.
SQL> col SEGMENT_NAME for a10
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST';
SEGMENT_NA EXTENTS BLOCKS INIT
---------- ---------- ---------- ----------
TEST 10 1280 10
SQL> col TABLE_NAME for a10
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST 0 1280
--TEST表初始分配了10M的空间,可以看到有10个EXTENTS,1280个BLOCKS。USER_TABLES视图显示有0个使用的BLOCKS,1280个空闲BLOCKS,即该10M空间内的BLOCK都还没被ORACLE”格式化”。
SQL> begin
2 for i in 1..100000 loop
3 insert into test values(i);
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL> analyze table test compute statistics;
Table analyzed.
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS from user_segments where SEGMENT_NAME='TEST';
SEGMENT_NA EXTENTS BLOCKS
---------- ---------- ----------
TEST 10 1280
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST 186 1094
--插入10W条数据后,分配的空间仍不变,因为10个EXTENTS还没使用完。显示使用了186个BLOCKS,空闲1094个BLOCKS。这时候的186BLOCKS即是高水位线
SQL> delete from test where rownum<=50000;
50000 rows deleted.
SQL> analyze table test compute statistics;
Table analyzed.
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS from user_segments where SEGMENT_NAME='TEST';
SEGMENT_NA EXTENTS BLOCKS
---------- ---------- ----------
TEST 10 1280
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST 186 1094
SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) used_blocks from test;
USED_BLOCKS
-----------
77
--这边可以看到,删掉一半数据后,仍然显示使用了186个BLOCKS,高水位没变。但查询真正使用的BLOCK数只有77个。所以DELETE操作是不会改变HWM的
SQL> alter table test move;
Table altered.
SQL> analyze table test compute statistics;
Table analyzed.
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST 81 1199
--MOVE之后,HWM降低了,空闲块也上去了
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS from user_segments where SEGMENT_NAME='TEST';
SEGMENT_NA EXTENTS BLOCKS
---------- ---------- ----------
TEST 10 1280
--但是分配的空间并没有改变,仍然是1280个BLOCKS。下面看用SHRINK SPACE的方式
SQL> alter table test enable row movement;
Table altered.
SQL> alter table test shrink space;
Table altered.
SQL> analyze table test compute statistics;
Table analyzed.
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS from user_segments where SEGMENT_NAME='TEST';
SEGMENT_NA EXTENTS BLOCKS
---------- ---------- ----------
TEST 1 88
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST 81 7
--分配的空间已经降到最小,1个EXTENTS ,88个BLOCKS
所以MOVE并不算真正意义上的压缩空间,只会压缩HWM以下的空间,消除碎片。我们一般建表时没有指定initial参数(默认是8个BLOCK),也就感觉不到这个差异。而SHRINK SPACE真正做到了对段的压缩,包括初始分配的也压了,所以它是blow and above HWM操作。
至于需要哪种方法,得看你的需求来了,需要分析表的增长情况,要是以后还会达到以前的HWM高度,那显然MOVE是更合适的,因为SHRINK SPACE还需要重新申请之前放掉的空间,无疑增加了操作。
注意:
1.不过用MOVE的方式也可以做到真正的压缩分配空间,只要指定STORAGE参数即可。
SQL> drop table test;
Table dropped.
SQL> create table test (id number) storage (initial 10m next 1m) tablespace users;
Table created.
SQL> analyze table test compute statistics;
Table analyzed.
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGME
NT_NAME='TEST';
SEGMENT_NA EXTENTS BLOCKS INIT
---------- ---------- ---------- ----------
TEST 10 1280 10
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST 0 1280
SQL>alter table test move storage (initial 1m);
Table altered.
SQL> analyze table test compute statistics;
Table analyzed.
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGME
NT_NAME='TEST';
SEGMENT_NA EXTENTS BLOCKS INIT
---------- ---------- ---------- ----------
TEST 16 128 1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST 0 128
2.使用move时,会改变一些记录的ROWID,所以MOVE之后索引会变为无效,需要REBUILD。
3.使用shrink space时,索引会自动维护。如果在业务繁忙时做压缩,可以先shrink space compact,来压缩数据而不移动HWM,等到不繁忙的时候再shrink space来移动HWM。
4.索引也是可以压缩的,压缩表时指定Shrink space cascade会同时压缩索引,也可以alter index xxx shrink space来压缩索引。
5.shrink space需要在表空间是自动段空间管理的,所以system表空间上的表无法shrink space。
---------------------------------------------------------------------------------------------------------------------------------------------
alter table move跟shrink space的区别
今天主要从两点说他们的区别:
1. 碎片的整理
2.空间的收缩
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - 64bi
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for Linux: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
SQL>
创建测试表
SQL> create table test3 as
2 select rownum id,
3 dbms_random.string('a', round(dbms_random.value(0,10))) col1,
4 trunc(sysdate) - dbms_random.value(1, 365*2) col2
5 from dual connect by rownum<=10000;
Table created
SQL> select count(1) from test3;
COUNT(1)
----------
10000
查看表test3的blocks使用情况:
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
*************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................32
Total bytes.............................262144
PL/SQL procedure successfully completed
制造碎片
SQL> DELETE FROM TEST3 WHERE MOD(ID,3)=1;
3334 rows deleted
SQL> commit;
Commit complete
发现有碎片了
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
*************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............31
25% -- 50% free space bytes.............253952
50% -- 75% free space blocks............1
50% -- 75% free space bytes.............8192
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................0
Total bytes.............................0
PL/SQL procedure successfully completed
SQL>
消除碎片
SQL> alter table test3 move;
Table altered
查看碎片消除的效果
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................32
Total Bytes.............................262144
Unused Blocks...........................6
Unused Bytes............................49152
Last Used Ext FileId....................31
Last Used Ext BlockId...................485065
Last Used Block.........................2
*************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................22
Total bytes.............................180224
PL/SQL procedure successfully completed
SQL>
从以上看,碎片整理的效果很好!!!
下面在测试用shrink整理碎片
重建测试环境
SQL> drop table test3;
Table dropped
SQL>
SQL> create table test3 as
2 select rownum id,
3 dbms_random.string('a', round(dbms_random.value(0,10))) col1,
4 trunc(sysdate) - dbms_random.value(1, 365*2) col2
5 from dual connect by rownum<=10000;
Table created
查看test3的blocks的使用
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
*************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................32
Total bytes.............................262144
PL/SQL procedure successfully completed
制造碎片
SQL> delete from test3 where mod(id,3)=1;
3334 rows deleted
SQL> commit;
Commit complete
查看碎片情况
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
*************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............31
25% -- 50% free space bytes.............253952
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................1
Total bytes.............................8192
PL/SQL procedure successfully completed
用oracle10g新功能整理碎片
SQL> alter table test3 shrink space compact cascade;
alter table test3 shrink space compact cascade
ORA-10636: ROW MOVEMENT is not enabled
SQL> alter table test3 enable row movement;
Table altered
SQL> alter table test3 shrink space compact cascade;
Table altered
再次查看碎片的情况,发现还有一些碎片,整理碎片效果不好
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................40
Total Bytes.............................327680
Unused Blocks...........................3
Unused Bytes............................24576
Last Used Ext FileId....................31
Last Used Ext BlockId...................481921
Last Used Block.........................5
*************************************************
0% -- 25% free space blocks.............1
0% -- 25% free space bytes..............8192
25% -- 50% free space blocks............2
25% -- 50% free space bytes.............16384
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........12
75% -- 100% free space bytes............98304
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................17
Total bytes.............................139264
PL/SQL procedure successfully completed
上面是没降低HWM,如果载降低HWM,看看效果
SQL> alter table test3 shrink space cascade;
Table altered
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................24
Total Bytes.............................196608
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................31
Last Used Ext BlockId...................481897
Last Used Block.........................8
*************************************************
0% -- 25% free space blocks.............1
0% -- 25% free space bytes..............8192
25% -- 50% free space blocks............2
25% -- 50% free space bytes.............16384
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................17
Total bytes.............................139264
PL/SQL procedure successfully completed
看来用shrink space整理碎片不彻底,再来看看move的方式
SQL> alter table test3 move;
Table altered
SQL> exec show_space_t('TEST3','auto','table','Y');
Total Blocks............................32
Total Bytes.............................262144
Unused Blocks...........................6
Unused Bytes............................49152
Last Used Ext FileId....................31
Last Used Ext BlockId...................485081
Last Used Block.........................2
*************************************************
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............0
25% -- 50% free space bytes.............0
50% -- 75% free space blocks............0
50% -- 75% free space bytes.............0
75% -- 100% free space blocks...........0
75% -- 100% free space bytes............0
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................22
Total bytes.............................180224
PL/SQL procedure successfully completed
效果很明显,整理的很彻底
测试结论:
虽然alter table move和shrink space,都是通过物理调整rowid来整理碎片的,但shrink space整理的不彻底,他好像不是重组,而是尽可能的合并,随意会残留一些block无法整理
注意:
1.再用alter table table_name move时,表相关的索引会失效,所以之后还要执行 alter index index_name rebuild online; 最后重新编译数据库所有失效的对象
2. 在用alter table table_name shrink space cascade时,他相当于alter table table_name move和alter index index_name rebuild online. 所以只要编译数据库失效的对象就可以
alter table move和shrink space除了碎片整理的效果有时不一样外,还有什么其他的不同呢
1. Move会移动高水位,但不会释放申请的空间,是在高水位以下(below HWM)的操作。
2. shrink space 同样会移动高水位,但也会释放申请的空间,是在高水位上下(below and above HWM)都有的操作。
下面通过实验来验证
SQL> drop table test3;
Table dropped
SQL>
SQL> create table test3 as
2 select rownum id,
3 dbms_random.string('a', round(dbms_random.value(0,10))) col1,
4 trunc(sysdate) - dbms_random.value(1, 365*2) col2
5 from dual connect by rownum<=10000;
Table created
SQL> analyze table test3 compute statistics;
Table analyzed
SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');
SEGMENT_NA EXTENTS BLOCKS
---------- ---------- ----------
TEST3 5 40
SQL> col table_name for a10;
SQL> select table_name,blocks,t.empty_blocks from user_tables t where t.table_name=upper('test3');
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3 37 3
SQL>
从以上查询可以看出共分了5个extents,使用了37个 blocks,这37也就是test3的HWM
SQL> delete from test3 where rownum<=5000;
5000 rows deleted
SQL> commit;
Commit complete
SQL> analyze table test3 compute statistics;
Table analyzed
SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');
SEGMENT_NA EXTENTS BLOCKS
---------- ---------- ----------
TEST3 5 40
SQL> col table_name for a10;
SQL> select table_name,blocks,t.empty_blocks from user_tables t where t.table_name=upper('test3');
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3 37 3
SQL> select count(distinct dbms_rowid.rowid_block_number(rowid)) used_blocks from test3;
USED_BLOCKS
-----------
17
我们从查询中可以发现test3的HWM没有变换还是 37blocks,tests总共空间为40blocks。经过删除后test3实际用的块是17个
下面我们用move降低下HWM
SQL> alter table test3 move;
Table altered
SQL> col segment_name for a10;
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');
SEGMENT_NA EXTENTS BLOCKS
---------- ---------- ----------
TEST3 3 24
SQL> col table_name for a10;
SQL> select table_name,blocks,t.empty_blocks from user_tables t where t.table_name=upper('test3');
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3 37 3
user_tables里的数据没有变化,哦,原来 是忘记analyze了,从这里也可以看出user_segments是oracle自动维护的。
SQL> analyze table test3 compute statistics;
Table analyzed
SQL> select us.segment_name,us.extents,us.blocks from user_segments us where us.segment_name=upper('test3');
SEGMENT_NA EXTENTS BLOCKS
---------- ---------- ----------
TEST3 3 24
SQL> select table_name,blocks,t.empty_blocks from user_tables t where t.table_name=upper('test3');
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST3 20 4
SQL>
现在再来看hwm变为20了,已经降下来了啊,空间也收缩 了,从40blocks降到24blocks(注意收缩到initial指定值)。
但shrink space就收缩到存储数据的最小值,下面测试说明
创建测试表:
SQL> create table test5 (id number) storage (initial 1m next 1m);
Table created
初始化数据
SQL>
SQL> begin
2 for i in 1..100000 loop
3 insert into test5 values(i);
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed
SQL> analyze table test5 compute statistics;
Table analyzed
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST5';
SEGMENT_NA EXTENTS BLOCKS INIT
---------- ---------- ---------- ----------
TEST5 17 256 1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST5';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5 180 76
可以从查询数据看出,test5初始化1m即128个blocks, 但数据比较多,所以又按next参数要求扩展了1m空间,扩展了17个extents。
这里的test5总空间大小为256个blocks,使用 空间为180blocks,HWM也是180blocks
SQL> delete from test5 where rownum<=50000;
50000 rows deleted
SQL> analyze table test5 compute statistics;
Table analyzed
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST5';
SEGMENT_NA EXTENTS BLOCKS INIT
---------- ---------- ---------- ----------
TEST5 17 256 1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST5';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5 180 76
整理碎片,降低HWM
SQL> alter table test5 move;
Table altered
SQL> analyze table test5 compute statistics;
Table analyzed
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST5';
SEGMENT_NA EXTENTS BLOCKS INIT
---------- ---------- ---------- ----------
TEST5 16 128 1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST5';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5 85 43
从上面的查询数据可以看出HWM已经从180降低到85,test5 总大小从256blocks收缩到128个blocks(initial指定大小)。
下面看看用shrink space收缩空间的情况
SQL> alter table test5 enable row movement;
Table altered
SQL> alter table test5 shrink space;
Table altered
SQL> select SEGMENT_NAME,EXTENTS,BLOCKS,INITIAL_EXTENT/1024/1024 init from user_segments where SEGMENT_NAME='TEST5';
SEGMENT_NA EXTENTS BLOCKS INIT
---------- ---------- ---------- ----------
TEST5 11 88 1
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from user_tables where table_name='TEST5';
TABLE_NAME BLOCKS EMPTY_BLOCKS
---------- ---------- ------------
TEST5 85 43
SQL>
从上面的数据可以看到test5进一步从128个blocks降低到88个blocks
结论:
shrink space收缩到数据存储的最小值,alter table move(不带参数)收缩到initial指定值,也可以用alter table test5 move storage(initial 500k)指定收缩的大小,这样可以达到shrink space效果
经过以上测试,得出的两个结论,到底用哪一个命令来整理碎片,消除行迁移呢?这就要根据实际业务需要,如果你只是收缩空间,数据增 长很慢,那用shrink可以但是如果数据增长很快的话,用move就比较合适,避免再重新分配空间啊
备注:
在10g之后,整理碎片消除行迁移的新 增功能shrink space
alter table shrink space [ | compact | cascade ];
compact :这个参数当系统的负载比较大时可以 用,不降低HWM。如果系统负载较低时,直接用alter table table_name shrink space就一步到位了
cascade :这个参数是在shrink table的时候自动级联索引,相当于rebulid index。
普通表:
shrink必须开启行迁移功能。
alter table table_name enable row movement ;
保持HWM,相当于把块中数据打结实了
alter table table_name shrink space compact;
回缩表与降低HWM
alter table table_name shrink space;
回缩表与相关索引,降低HWM
alter table table_name shrink space cascade;
回缩索引与降低HWM
alter index index_name shrink space
虽然在10g中可以用shrink ,但也有些限制:
1). 对cluster,cluster table,或具有Long,lob类型列的对象 不起作用。
2). 不支持具有function-based indexes 或 bitmap join indexes的表
3). 不支持mapping 表或index-organized表。
4). 不支持compressed 表
通过前面两节学习可知,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命令可以释放空间(当然这语句最根本的作用还是移动表到不同的表空间去,这里只是借用它可以释放空间的一个特性),还要了解该动作会锁表直到命令结束,而且会导致索引失效,属于危险命令,建议千万不要在业务高峰期操作。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)