Shrink详解.docx

上传人:b****5 文档编号:7684640 上传时间:2023-01-25 格式:DOCX 页数:12 大小:147.76KB
下载 相关 举报
Shrink详解.docx_第1页
第1页 / 共12页
Shrink详解.docx_第2页
第2页 / 共12页
Shrink详解.docx_第3页
第3页 / 共12页
Shrink详解.docx_第4页
第4页 / 共12页
Shrink详解.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

Shrink详解.docx

《Shrink详解.docx》由会员分享,可在线阅读,更多相关《Shrink详解.docx(12页珍藏版)》请在冰豆网上搜索。

Shrink详解.docx

Shrink详解

从10g开始,oracle开始提供Shrink的命令,假如我们的表空间中支持自动段空间管理 (ASSM),就可以使用这个特性缩小段,即降低HWM。

这里需要强调一点,10g的这个新特性,仅对ASSM表空间有效,否则会报 ORA-10635:

Invalidsegmentortablespacetype。

 

如果经常在表上执行DML操作,会造成数据库块中数据分布稀疏,浪费大量空间。

同时也会影响全表扫描的性能,因为全表扫描需要访问更多的数据块。

从oracle10g开始,表可以通过shrink来重组数据使数据分布更紧密,同时降低HWM释放空闲数据块。

segmentshrink分为两个阶段:

 

1、数据重组(compact)

通过一系列insert、delete操作,将数据尽量排列在段的前面。

在这个过程中需要在表上加RX锁,即只在需要移动的行上加锁。

由于涉及到rowid的改变,需要enablerowmovement.同时要disable基于rowid的trigger.这一过程对业务影响比较小。

2、HWM调整

第二阶段是调整HWM位置,释放空闲数据块。

此过程需要在表上加X锁,会造成表上的所有DML语句阻塞。

在业务特别繁忙的系统上可能造成比较大的影响。

shrinkspace语句两个阶段都执行。

shrinkspacecompact只执行第一个阶段。

如果系统业务比较繁忙,可以先执行shrinkspacecompact重组数据,然后在业务不忙的时候再执行shrinkspace降低HWM释放空闲数据块。

shrink必须开启行迁移功能。

altertabletable_nameenablerowmovement;

注意:

altertableXXXenablerowmovement语句会造成引用表XXX的对象(如存储过程、包、视图等)变为无效。

执行完成后,最好执行一下utlrp.sql来编译无效的对象。

语法:

altertableshrinkspace[|compact|cascade];

其中:

altertableshrinkspacecompcat;

收缩表,相当于把块中数据打结实了,但会保持 highwatermark;

altertableshrinkspace;

收缩表,降低 highwatermark;

altertableshrinkspacecascade;

收缩表,降低 highwatermark,并且相关索引也要收缩一下。

 

alterindexidxnameshrinkspace;

回缩索引

1:

普通表

Sql脚本,该脚本会生成相应的语句:

select'altertable'||table_name||'enablerowmovement;'||chr(10)||'altertable'||table_name||'shrinkspace;'||chr(10)fromuser_tables;

select'alterindex'||index_name||'shrinkspace;'||chr(10)fromuser_indexes;

2:

分区表的处理

进行shrinkspace时 发生ORA-10631错误.shrinkspace有一些限制.

在表上建有函数索引(包括全文索引)会失败。

 Sql脚本,改脚本会生成相应的语句:

select'altertable'||table_name||'enablerowmovement;'||chr(10)||'altertable'||table_name||'shrinkspace;'||chr(10)fromuser_tables;

 select'alterindex'||index_name||'shrinkspace;'||chr(10)fromuser_indexeswhereuniqueness='NONUNIQUE';

select'altertable'||segment_name||'modifysubpartition'||partition_name||'shrinkspace;'||chr(10)fromuser_segmentswheresegment_type='TABLESUBPARTITION';

详细测试:

我们用系统视图all_objects来在上个测试的tablespaceASSM上创建测试表my_objects

SELECT   TABLESPACE_NAME,

         BLOCK_SIZE,

         EXTENT_MANAGEMENT,

         ALLOCATION_TYPE,

         SEGMENT_SPACE_MANAGEMENT

  FROM   dba_tablespaces

 WHERE   TABLESPACE_NAME = 'HECV';

 

CREATE TABLE my_objects

TABLESPACE hecv

AS

   SELECT   * FROM all_objects;

 

然后我们随机地从tableMY_OBJECTS中删除一部分数据:

SQL> SELECT   COUNT (*) FROM my_objects;

SQL>deletefrommy_objectswhereobject_namelike'%C%';

SQL>deletefrommy_objectswhereobject_namelike'%U%';

SQL>deletefrommy_objectswhereobject_namelike'%A%';

现在我们使用show_space()来看看my_objects的数据存储状况:

 

SQL>exec show_space('my_objects','auto','T','Y');

这里,tablemy_objects的HWM下有1152个block,其中,freespace为25-50%的block有303个,freespace为50-75%的block有284个,freespace为75-100%的block有409个.Totalblocks11个。

这种情况下,我们需要对这个table的现有数据行进行重组。

要使用assm上的shink,首先我们需要使该表支持行移动,可以用这样的命令来完成:

altertablemy_objectsenablerowmovement;

现在,就可以来降低my_objects的HWM,回收空间了,使用命令:

altertablebookingsshrinkspace;

我们具体的看一下实验的结果:

SQL>exec show_space('my_objects','auto','T','Y');

 

在执行玩shrink命令后,我们可以看到,tablemy_objects的HWM现在降到了456的位置,而且HWM下的block的空间使用状况,Totalblocks 的block有430个,freespace 为25-50%Block只有1个。

Shrink 的实现机制:

我们接下来讨论一下shrink的实现机制,我们同样使用讨论move机制的那个实验来观察。

CREATE TABLE TEST_HWM (id  INT, name CHAR (2000))

TABLESPACE hecv;

 

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和信息:

SQL>SELECT   ROWID, id, name FROM TEST_HWM;

SQL>SELECT   EXTENT_ID,

         FILE_ID,

         RELATIVE_FNO,

         BLOCK_ID,

         BLOCKS

  FROM   dba_extents

 WHERE   segment_name = 'TEST_HWM';

 

然后从tabletest_hwm中删除一些数据:

deletefromTEST_HWMwhereid=2;

deletefromTEST_HWMwhereid=4;

deletefromTEST_HWMwhereid=3;

deletefromTEST_HWMwhereid=7;

deletefromTEST_HWMwhereid=8;

 

观察tabletest_hwm的rowid和blockid的信息:

SQL>selectrowid,id,namefromTEST_HWM;

 

 

 

从以上的信息,我们可以看到,在tabletest_hwm中,剩下的数据是分布在AAA10z,AAA100,AAA102,AAA103这样四个连续的block中。

 

SQL> exec show_space('TEST_HWM','auto','T','Y');

我们可以看到目前这四个block的空间使用状况,AAA10z,AAA100,AAA103上各有一行数据,我们猜测freespace为50-75%的3个block是这三个block,那么freespace为25-50%的1个block就是AAA102了,剩下freespace为 75-100% 的1个block,是HWM下已格式化的尚未使用的block。

然后,我们对tablemy_objects执行shtink的操作:

SQL>altertabletest_hwmenablerowmovement;

SQL>altertabletest_hwmshrinkspace;

SQL>selectrowid,id,namefromTEST_HWM;

SQL>SELECT   EXTENT_ID,

         FILE_ID,

         RELATIVE_FNO,

         BLOCK_ID,

         BLOCKS

  FROM   dba_extents

 WHERE   segment_name = 'TEST_HWM';

 

 

当执行了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之前,(9,es)被移动到blockAAA10z上,写到(1,aa)这行数据的后面,所以(9,es)的rowid发生改变。

然后是(6,es)这行数据,重复上述过程。

这是oracle从后向前移动行数据的大致遵循的规则,那么具体移动行数据的的算法是比较复杂的,包括向ASSM的table中insert数据使用block的顺序的算法也是比较复杂的,大家有兴趣的可以自己来研究,在这里我们不多做讨论。

在shrinktable的同时shrink这个table上的index:

altertablemy_objectsshrinkspacecascade;

同样地,这个操作只有当table上的index也是ASSM时,才能使用。

Move 和 Shrink 产生日志的对比

我们对比了同样数据量和分布状况的两张table,在move和shrink下生成的redosize(table上没有index的情况下):

SQL>SELECT   tablespace_name, SEGMENT_SPACE_MANAGEMENT

  FROM   dba_tablespaces

WHERE   tablespace_name IN ('HECV');

 

SQL>createtablemy_objectstablespaceHECVasselect*fromall_objectswhererownum<20000;

SQL>createtablemy_objects1tablespaceHECV_FRONTasselect*fromall_objectswhererownum<20000;

SQL>selectbytes/1024/1024fromuser_segmentswheresegment_name='MY_OBJECTS';

SQL>deletefrommy_objectswhereobject_namelike'%C%';

SQL>deletefrommy_objects1whereobject_namelike'%C%';

SQL>deletefrommy_objectswhereobject_namelike'%U%';

SQL>deletefrommy_objects1whereobject_namelike'%U%';

SQL>altertablemy_objectsenablerowmovement;

SQL>SELECT   VALUE

  FROM   v$mystat, v$statname

 WHERE   v$mystat.statistic# = v$statname.statistic#

         AND v$statname.name = 'redosize';

SQL>altertablemy_objectsshrinkspace;

SQL>SELECT   VALUE

  FROM   v$mystat, v$statname

 WHERE   v$mystat.statistic# = v$statname.statistic#

         AND v$statname.name = 'redosize';

SQL>altertablemy_objects1move;

SQL>SELECT   VALUE

  FROM   v$mystat, v$statname

 WHERE   v$mystat.statistic# = v$statname.statistic#

         AND v$statname.name = 'redosize';

对于tablemy_objects,进行shrink,产生了21148396–16762668=4385728,约4.2M的redo ;

对tablemy_objects1进行move,产生了21212908-21148396=64512,约63K的redosize。

 结论:

与move比较起来,shrink的日志写要大得多。

Shrink的几点问题:

1.      shrink后index是否需要rebuild:

因为shrink的操作也会改变行数据的rowid,那么,如果table上有index时,shrinktable后index会不会变为UNUSABLE呢?

我们来看这样的实验,同样构建my_objects的测试表:

createtablemy_objectstablespacehecvasselect*fromall_objectswhererownum<20000;

createindexi_my_objectsonmy_objects(object_id);

deletefrommy_objectswhereobject_namelike'%C%';

deletefrommy_objectswhereobject_namelike'%U%';

现在我们来shrinktablemy_objects:

SQL>altertablemy_objectsenablerowmovement;

SQL>altertablemy_objectsshrinkspace;

SQL>selectindex_name,statusfromuser_indexeswhereindex_name='I_MY_OBJECTS';

我们发现,tablemy_objects上的index的状态为VALID,估计shrink在移动行数据时,也一起维护了index上相应行的数据rowid的信息。

我们认为,这是对于move操作后需要rebuildindex的改进。

但是如果一个table上的index数量较多,我们知道,维护index的成本是比较高的,shrink过程中用来维护index的成本也会比较高。

2.shrink时对table的lock

在对table进行shrink时,会对table进行怎样的锁定呢?

当我们对tableMY_OBJECTS进行shrink操作时,查询v$locked_objects视图可以发现,tableMY_OBJECTS上加了row-X(SX) 的lock:

SQL>selectOBJECT_ID,SESSION_ID,ORACLE_USERNAME,LOCKED_MODEfromv$locked_objects;

OBJECT_IDSESSION_IDORACLE_USERNAMELOCKED_MODE

-------------------------------------------------

55422153DLINGER3

SQL>selectobject_idfromuser_objectswhereobject_name='MY_OBJECTS';

OBJECT_ID

----------

55422

那么,当table在进行shrink时,我们对table是可以进行DML操作的。

3.shrink对空间的要求

我们在前面讨论了shrink的数据的移动机制,既然oracle是从后向前移动行数据,那么,shrink的操作就不会像move一样,shrink不需要使用额外的空闲空间。

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 法律文书 > 判决书

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1