- 浏览: 1218971 次
文章分类
最新评论
-
netkongjian:
欢迎加入程序员网址导航[deyi]
准备做一个技术网址导航,请大家分享自己喜欢的技术网站 -
jinshi:
漫画阅读器代码呢?
Android 值得收藏的Demo -
javaboy2010:
非常不错!
老程序员从头开始学JQuery的读书笔记 -
hzfeibao:
很佩服这位仁兄的学习精神和良好的学习习惯,我自己学东西从来都是 ...
老程序员从头开始学JQuery的读书笔记 -
paradigm:
agree
我几年的工作心得,一个菜鸟DBA的心得
Oracle 10g Shrink Table 详解
从10g开始,oracle开始提供Shrink的命令,假如我们的表空间中支持自动段空间管理 (ASSM),就可以使用这个特性缩小段,即降低HWM。这里需要强调一点,10g的这个新特性,仅对ASSM表空间有效,否则会报 ORA-10635: Invalid segment or tablespace type。
有关ASSM的详细信息,请参考我的Blog:Oracle 自动段空间管理
http://blog.csdn.net/tianlesoftware/archive/2009/12/07/4958989.aspx
如果经常在表上执行DML操作,会造成数据库块中数据分布稀疏,浪费大量空间。同时也会影响全表扫描的性能,因为全表扫描需要访问更多的数据块。从oracle10g开始,表可以通过shrink来重组数据使数据分布更紧密,同时降低HWM释放空闲数据块。
segment shrink分为两个阶段:
1、数据重组(compact):通过一系列insert、delete操作,将数据尽量排列在段的前面。在这个过程中需要在表上加RX锁,即只在需要移动的行上加锁。由于涉及到rowid的改变,需要enable row movement.同时要disable基于rowid的trigger.这一过程对业务影响比较小。
2、HWM调整:第二阶段是调整HWM位置,释放空闲数据块。此过程需要在表上加X锁,会造成表上的所有DML语句阻塞。在业务特别繁忙的系统上可能造成比较大的影响。
shrink space语句两个阶段都执行。
shrink space compact只执行第一个阶段。
如果系统业务比较繁忙,可以先执行shrink space compact重组数据,然后在业务不忙的时候再执行shrink space降低HWM释放空闲数据块。
shrink必须开启行迁移功能。
alter table table_name enable row movement ;
注意:alter table XXX enable row movement语句会造成引用表XXX的对象(如存储过程、包、视图等)变为无效。执行完成后,最好执行一下utlrp.sql来编译无效的对象。
语法:
alter table <table_name> shrink space [ <null> | compact | cascade ];
alter table <table_name> shrink space compcat;
收缩表,相当于把块中数据打结实了,但会保持 high water mark;
alter table <tablespace_name> shrink space;
收缩表,降低 high water mark;
alter table <tablespace_name> shrink space cascade;
收缩表,降低 high water mark,并且相关索引也要收缩一下下。
alter index idxname shrink space;
回缩索引
1:普通表
Sql脚本,改脚本会生成相应的语句
select'alter table '||table_name||' enable row movement;'||chr(10)||'alter table '||table_name||' shrink space;'||chr(10)from user_tables;
select'alter index '||index_name||' shrink space;'||chr(10)from user_indexes;
2:分区表的处理
进行shrink space时 发生ORA-10631错误.shrink space有一些限制.
在表上建有函数索引(包括全文索引)会失败。
Sql脚本,改脚本会生成相应的语句
select 'alter table '||table_name||' enable row movement;'||chr(10)||'alter table '||table_name||' shrink space;'||chr(10) from user_tables where ;
select 'alter index '||index_name||' shrink space;'||chr(10) from user_indexes where uniqueness='NONUNIQUE' ;
select 'alter table '||segment_name||' modify subpartition '||partition_name||' shrink space;'||chr(10) from user_segments where segment_type='TABLE SUBPARTITION' ';
详细测试:
我们用系统视图all_objects来在上个测试的tablespace ASSM上创建测试表my_objects
/* Formatted on 2009-12-7 20:42:45 (QP5 v5.115.810.9015) */
CREATE TABLESPACE ASSM DATAFILE 'd:/ASSM01.dbf' SIZE 100M EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO;
/* Formatted on 2009-12-7 20:39:26 (QP5 v5.115.810.9015) */
SELECT TABLESPACE_NAME,
BLOCK_SIZE,
EXTENT_MANAGEMENT,
ALLOCATION_TYPE,
SEGMENT_SPACE_MANAGEMENT
FROM dba_tablespaces
WHERE TABLESPACE_NAME = 'ASSM';
TABLESPACE_NAME BLOCK_SIZE EXTENT_MAN ALLOCATIO SEGMEN
--------------------- ---------- ---------- --------- ------
ASSM 8192 LOCAL SYSTEM AUTO
1 row selected.
/* Formatted on 2009-12-7 20:44:15 (QP5 v5.115.810.9015) */
CREATE TABLE my_objects
TABLESPACE assm
AS
SELECT * FROM all_objects;
然后我们随机地从table MY_OBJECTS中删除一部分数据:
SQL> SELECT COUNT ( * ) FROM my_objects;
COUNT(*)
----------
49477
SQL> delete from my_objects where object_name like '%C%';
SQL> delete from my_objects where object_name like '%U%';
SQL> delete from my_objects where object_name like '%A%';
现在我们使用show_space()来看看my_objects的数据存储状况:
注: show_space() 存储过程代码参看一下连接的附件
http://blog.csdn.net/tianlesoftware/archive/2009/12/07/4958989.aspx
SQL>exec show_space('my_objects','auto','T','Y');
Total Blocks............................768
Total Bytes.............................6291456
Unused Blocks...........................68
Unused Bytes............................557056
Last Used Ext FileId....................8
Last Used Ext BlockId...................649
Last Used Block.........................60
*************************************************
The segment is analyzed
0% -- 25% free space blocks.............41
0% -- 25% free space bytes..............335872
25% -- 50% free space blocks............209
25% -- 50% free space bytes.............1712128
50% -- 75% free space blocks............190
50% -- 75% free space bytes.............1556480
75% -- 100% free space blocks...........229
75% -- 100% free space bytes............1875968
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................11
Total bytes.............................90112
PL/SQL 过程已成功完成。
这里,table my_objects的HWM下有767个block,其中,free space为25-50%的block有209个,free space为50-75%的block有190个,free space为75-100%的block有229个. Total blocks 11个。
这种情况下,我们需要对这个table的现有数据行进行重组。
要使用assm上的shink,首先我们需要使该表支持行移动,可以用这样的命令来完成:
alter table my_objects enable row movement;
现在,就可以来降低my_objects的HWM,回收空间了,使用命令:
alter table bookings shrink space;
我们具体的看一下实验的结果:
SQL> alter table my_objects enable row movement;
表已更改。
SQL> alter table my_objects shrink space;
表已更改。
SQL>exec show_space('my_objects','auto','T','Y');
Total Blocks............................272
Total Bytes.............................2228224
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................8
Last Used Ext BlockId...................265
Last Used Block.........................16
*************************************************
The segment is analyzed
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............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............................257
Total bytes.............................2105344
在执行玩shrink命令后,我们可以看到,table my_objects的HWM现在降到了271的位置,而且HWM下的block的空间使用状况,Total blocks 的block有257个,free space 为25-50% Block只有0个。
Shrink 的实现机制:
我们接下来讨论一下shrink的实现机制,我们同样使用讨论move机制的那个实验来观察。
/* Formatted on 2009-12-7 20:58:40 (QP5 v5.115.810.9015) */
CREATE TABLE TEST_HWM (id INT, name CHAR (2000))
TABLESPACE ASSM;
INSERT INTO TEST_HWM VALUES (1, 'aa');
INSERT INTO TEST_HWM VALUES (2, 'bb');
INSERT INTO TEST_HWM VALUES (2, 'cc');
INSERT INTO TEST_HWM VALUES (3, 'dd');
INSERT INTO TEST_HWM VALUES (4, 'ds');
INSERT INTO TEST_HWM VALUES (5, 'dss');
INSERT INTO TEST_HWM VALUES (6, 'dss');
INSERT INTO TEST_HWM VALUES (7, 'ess');
INSERT INTO TEST_HWM VALUES (8, 'es');
INSERT INTO TEST_HWM VALUES (9, 'es');
INSERT INTO TEST_HWM VALUES (10, 'es');
我们来看看这个table的rowid和block的ID和信息:
/* Formatted on 2009-12-7 21:00:02 (QP5 v5.115.810.9015) */
SQL>SELECT ROWID, id, name FROM TEST_HWM;ROWID ID NAME
ROWID ID NAME
------------------------------------- ---------- --------
AAANMEAAIAAAAEcAAA 3 dd
AAANMEAAIAAAAEcAAB 4 ds
AAANMEAAIAAAAEcAAC 5 dss
AAANMEAAIAAAAEdAAA 6 dss
AAANMEAAIAAAAEdAAB 7 ess
AAANMEAAIAAAAEdAAC 8 es
AAANMEAAIAAAAEeAAA 9 es
AAANMEAAIAAAAEeAAB 10 es
AAANMEAAIAAAAEgAAA 1 aa
AAANMEAAIAAAAEgAAB 2 bb
AAANMEAAIAAAAEgAAC 2 cc
/* Formatted on 2009-12-7 21:00:49 (QP5 v5.115.810.9015) */
SQL>SELECT EXTENT_ID,
FILE_ID,
RELATIVE_FNO,
BLOCK_ID,
BLOCKS
FROM dba_extents
WHERE segment_name = 'TEST_HWM';
EXTENT_ID FILE_ID RELATIVE_FNO BLOCK_ID BLOCKS
---------- ---------- ------------ ---------- ----------
0 8 8 281 8
1 row selected.
然后从table test_hwm中删除一些数据:
delete from TEST_HWM where id = 2;
delete from TEST_HWM where id = 4;
delete from TEST_HWM where id = 3;
delete from TEST_HWM where id = 7;
delete from TEST_HWM where id = 8;
观察table test_hwm的rowid和blockid的信息:
SQL> select rowid , id,name from TEST_HWM;
ROWID ID NAME
------------------------------------------ ---------- ---------
AAANMEAAIAAAAEcAAC 5 dss
AAANMEAAIAAAAEdAAA 6 dss
AAANMEAAIAAAAEeAAA 9 es
AAANMEAAIAAAAEeAAB 10 es
AAANMEAAIAAAAEgAAA 1 aa
/* Formatted on 2009-12-7 21:00:49 (QP5 v5.115.810.9015) */
SQL>SELECT EXTENT_ID,
FILE_ID,
RELATIVE_FNO,
BLOCK_ID,
BLOCKS
FROM dba_extents
WHERE segment_name = 'TEST_HWM';
EXTENT_ID FILE_ID RELATIVE_FNO BLOCK_ID BLOCKS
---------- ---------- ------------ ---------- ----------
0 8 8 281 8
1 row selected.
从以上的信息,我们可以看到,在table test_hwm中,剩下的数据是分布在AAAAEc,AAAAEd,AAAAEf,AAAAEg这样四个连续的block中。
SQL> exec show_space('TEST_HWM','auto','T','Y');
Total Blocks............................8
Total Bytes.............................65536
Unused Blocks...........................0
Unused Bytes............................0
Last Used Ext FileId....................8
Last Used Ext BlockId...................281
Last Used Block.........................8
*************************************************
The segment is analyzed
0% -- 25% free space blocks.............0
0% -- 25% free space bytes..............0
25% -- 50% free space blocks............1
25% -- 50% free space bytes.............8192
50% -- 75% free space blocks............3
50% -- 75% free space bytes.............24576
75% -- 100% free space blocks...........1
75% -- 100% free space bytes............8192
Unused Blocks...........................0
Unused Bytes............................0
Total Blocks............................0
Total bytes.............................0
我们可以看到目前这四个block的空间使用状况,AAAAEc,AAAAEd,AAAAEf,AAAAEg上各有一行数据,我们猜测free space为50-75%的3个block是这三个block,那么free space为25-50%的1个block就是AAAAEg了,剩下free space为 75-100% 的3个block,是HWM下已格式化的尚未使用的block。(在extent不大于于16个block时,是以一个extent为单位来移动的)
然后,我们对table my_objects执行shtink的操作:
SQL> alter table test_hwm enable row movement;
Table altered
SQL> alter table test_hwm shrink space;
Table altered
SQL> select rowid ,id,name from TEST_HWM;
ROWID ID NAME
------------------ ---------- ------------
AAANMEAAIAAAAEcAAA 10 es
AAANMEAAIAAAAEcAAC 5 dss
AAANMEAAIAAAAEcAAD 1 aa
AAANMEAAIAAAAEcAAE 9 es
AAANMEAAIAAAAEdAAA 6 dss
/* Formatted on 2009-12-7 21:00:49 (QP5 v5.115.810.9015) */
SQL>SELECT EXTENT_ID,
FILE_ID,
RELATIVE_FNO,
BLOCK_ID,
BLOCKS
FROM dba_extents
WHERE segment_name = 'TEST_HWM';
EXTENT_ID FILE_ID RELATIVE_FNO BLOCK_ID BLOCKS
---------- ---------- ------------ ---------- ----------
0 8 8 281 8
1 row selected.
当执行了shrink操作后,有意思的现象出现了。我们来看看oracle是如何移动行数据的,这里的情况和move已经不太一样了。我们知道,在move操作的时候,所有行的rowid都发生了变化,table所位于的block的区域也发生了变化,但是所有行物理存储的顺序都没有发生变化,所以我们得到的结论是,oracle以block为单位,进行了block间的数据copy。那么shrink后,我们发现,部分行数据的rowid发生了变化,同时,部分行数据的物理存储的顺序也发生了变化,而table所位于的block的区域却没有变化,这就说明,shrink只移动了table其中一部分的行数据,来完成释放空间,而且,这个过程是在table当前所使用的block中完成的。
那么Oracle具体移动行数据的过程是怎样的呢?我们根据这样的实验结果,可以来猜测一下:
Oracle是以行为单位来移动数据的。Oracle从当前table存储的最后一行数据开始移动,从当前table最先使用的block开始搜索空间,所以,shrink之前,rownum=10的那行数据(10,es),被移动到block AAAAEc上,写到(1,aa)这行数据的后面,所以(10,es)的rownum和rowid同时发生改变。然后是(9,es)这行数据,重复上述过程。这是oracle从后向前移动行数据的大致遵循的规则,那么具体移动行数据的的算法是比较复杂的,包括向ASSM的table中insert数据使用block的顺序的算法也是比较复杂的,大家有兴趣的可以自己来研究,在这里我们不多做讨论。
在shrink table的同时shrink这个table上的index:
alter table my_objects shrink space cascade;
同样地,这个操作只有当table上的index也是ASSM时,才能使用。
Move 和 Shrink 产生日志的对比
我们对比了同样数据量和分布状况的两张table,在move和shrink下生成的redo size(table上没有index的情况下):
/* Formatted on 2009-12-7 21:20:43 (QP5 v5.115.810.9015) */
SQL>SELECT tablespace_name, SEGMENT_SPACE_MANAGEMENT
FROM dba_tablespaces
WHERE tablespace_name IN ('ASSM', 'HWM');
TABLESPACE_NAME SEGMENT_SPACE_MANAGEMENT
------------------------------ ------------------------
ASSM AUTO
HWM MANUAL
SQL> create table my_objects tablespace ASSM as select * from all_objects where rownum<20000;
Table created
SQL> create table my_objects1 tablespace HWM as select * from all_objects where rownum<20000;
Table created
SQL> select bytes/1024/1024 from user_segments where segment_name = 'MY_OBJECTS';
BYTES/1024/1024
---------------
2.1875
SQL> delete from my_objects where object_name like '%C%';
7278 rows deleted
SQL> delete from my_objects1 where object_name like '%C%';
7278 rows deleted
SQL> delete from my_objects where object_name like '%U%';
2732 rows deleted
SQL> delete from my_objects1 where object_name like '%U%';
2732 rows deleted
SQL> commit;
Commit complete
SQL> alter table my_objects enable row movement;
Table altered
/* Formatted on 2009-12-7 21:21:48 (QP5 v5.115.810.9015) */
SQL>SELECT VALUE
FROM v$mystat, v$statname
WHERE v$mystat.statistic# = v$statname.statistic#
AND v$statname.name = 'redo size';
VALUE
----------
27808792
SQL> alter table my_objects shrink space;
Table altered
SQL>SELECT VALUE
FROM v$mystat, v$statname
WHERE v$mystat.statistic# = v$statname.statistic#
AND v$statname.name = 'redo size';
VALUE
----------
32579712
SQL> alter table my_objects1 move;
Table altered
SQL>SELECT VALUE
FROM v$mystat, v$statname
WHERE v$mystat.statistic# = v$statname.statistic#
AND v$statname.name = 'redo size';
VALUE
----------
32676784
对于table my_objects,进行shrink,产生了32579712 – 27808792=4770920,约4.5M的redo ;对table my_objects1进行move,产生了32676784-32579712= 97072,约95K的redo size。
结论:与move比较起来,shrink的日志写要大得多。
Shrink的几点问题:
1. shrink后index是否需要rebuild:
因为shrink的操作也会改变行数据的rowid,那么,如果table上有index时,shrink table后index会不会变为UNUSABLE呢?
我们来看这样的实验,同样构建my_objects的测试表:
create table my_objects tablespace ASSM as select * from all_objects where rownum<20000;
create index i_my_objects on my_objects (object_id);
delete from my_objects where object_name like '%C%';
delete from my_objects where object_name like '%U%';
现在我们来shrink table my_objects:
SQL> alter table my_objects enable row movement;
Table altered
SQL> alter table my_objects shrink space;
Table altered
SQL> select index_name,status from user_indexes where index_name='I_MY_OBJECTS';
INDEX_NAME STATUS
------------------------------ --------
I_MY_OBJECTS VALID
我们发现,table my_objects上的index的状态为VALID,估计shrink在移动行数据时,也一起维护了index上相应行的数据rowid的信息。我们认为,这是对于move操作后需要rebuild index的改进。但是如果一个table上的index数量较多,我们知道,维护index的成本是比较高的,shrink过程中用来维护index的成本也会比较高。
2. shrink时对table的lock
在对table进行shrink时,会对table进行怎样的锁定呢?当我们对table MY_OBJECTS进行shrink操作时,查询v$locked_objects视图可以发现,table MY_OBJECTS上加了row-X (SX) 的lock:
SQL>select OBJECT_ID, SESSION_ID,ORACLE_USERNAME,LOCKED_MODE from v$locked_objects;
OBJECT_ID SESSION_ID ORACLE_USERNAME LOCKED_MODE
---------- ---------- ------------------ -----------
55422 153 DLINGER 3
SQL> select object_id from user_objects where object_name = 'MY_OBJECTS';
OBJECT_ID
----------
55422
那么,当table在进行shrink时,我们对table是可以进行DML操作的。
3. shrink对空间的要求
我们在前面讨论了shrink的数据的移动机制,既然oracle是从后向前移动行数据,那么,shrink的操作就不会像move一样,shrink不需要使用额外的空闲空间。
相关推荐
解决Oracle 碎片整理 问题。比较Oracle中的alter table t move和alter table t shrink space。Oracle 10g Shrink Table 详解。
因此oracle提供了shrink space碎片整理功能。对于索引,可以采取rebuild online的方式进行碎片整理,一般来说,经常进行DML操作的对象DBA要定期进行维护,同时注意要及时更新统计信息!一:准备测试数据,使用HR用户...
oracle数据表碎片整理 alter table <table_name> shrink space [ <null> | compact | cascade ];
ORACLE常用命令 一、ORACLE的启动和关闭 1、在单机环境下 要想启动或关闭ORACLE系统必须首先切换到ORACLE用户,如下 su - oracle a、启动ORACLE系统 oracle>svrmgrl SVRMGR>connect internal SVRMGR>startup ...
WinMP3Shrink 音乐压缩软件
1.领域:matlab,Shrink小波变换算法 2.内容:基于Shrink小波变换的数据去噪可以设置硬阈值和软阈值+代码操作视频 3.用处:用于Shrink小波变换算法编程学习 4.指向人群:本硕博等教研学习使用 5.运行注意事项:...
PDF Shrink是一个PDF文件体积压缩器,生成的文件大小适合作为电子邮件附件或在手机屏幕上阅读。PDF Shrink还可以进行文件压缩以减少生PDF文件的大小。
环境:OS:Red Hat Enterprise Linux AS release 4 (Nahant)DB:Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Production 一台Oracle10gR2数据库报出如下错误:ORA-1653: unable to extend table ...
这个程序是为了实现图片(包括彩色图和灰度图)的放缩功能,能满足任意指定放缩倍数或任意目标尺寸,原理是依据双线性插值。
这是一个基于Matlab平台实现的图像放缩的代码,可以实现任意倍数,任意指定尺寸的放缩要求。原理是基于最近点近似。
0.13um-shrink工艺的嵌入式闪存的耐久性特性研究_V2.0.zip
Oracle Database 10g Release 2 introduced Transportable Database (TDB), which reduces the amount of time and effort required to migrate a database between platforms that share the same endian format ...
前端开源库-shrink-ray-current收缩光线流,node.js压缩中间件,支持brotli和zopfli
DVD影片备份工具(DVD Shrink) 3.20 绿色汉化版
本篇文章给大家带来的内容是关于flex-shrink如何计算?flex-shrink的计算方法介绍,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助
可将PDF压缩。一般办公网络传输 压缩50%-80%
近期来,FreeList的重要作用逐渐为Oracle DBA所认识,网上也出现一些相关的讨论。本文以FreeList为线索对Oracle的存储管理的原理进行较深入的探讨,涉及Oracle段区块管理的原理,FreeList算法等。而与FreeList密切...
这个工具很好的压缩了数据库日志文件的大小。 操作简单,输入服务器名,帐号密码,数据库名就OK。
0.13um-shrink工艺的嵌入式闪存的耐久性特性研究_V2.0 字数.zip
PDF 专用压缩软件 PDF shrink