Oracle 10g以后版本推出的shrink操作大家并不陌生,以下截取部分Oracle官方文档介绍,今天我们来重温部分shrink操作的案例
The segment shrink operation reclaims unused space from above and below the high water mark. Unlike space de-allocation which only reclaims space above the high water mark, the shrink operation compacts the object and adjusts the high water mark before releasing the unused space.Segment shrink is an online operation which allows DML operations to be issued during the data movement phase of the shrink. However, DML operations are blocked for a short time at the end of the shrink operation when the space is de-allocated. Indexes are maintained during the shrink and remain usable after the shrink is complete
1.基于索引的shrink操作
1.1实际上索引shrink操作会扫描索引的页块,并且通过归并当前存在的数据将先前已删除记录的空间重新利用,下面我们通过案例来验证一下coalesce方式和shrink方式的性能消耗和区别。
1.2coalesce功能测试:


注意:
1.HEIGHT :B-Tree索引高度
2.BLOCKS :分配给段的块
3.LF_BLKS :B-Tree的叶子块数量
4.LF_ROWS_LEN :所有叶行长度的总和
5.LF_BLK_LEN :叶块中的可用空间
6.BR_BLKS :B-Tree中分支块的数量
7.BR_ROWS :B-Tree中的分支块长度
8.BR_ROWS_LEN :B-Tree中所有分支块长度之和
9.BR_BLK_LEN :分支块中的可用空间
10.BTREE_SPACE :当前B-Tree分配的总空间
11.USED_SPACE :当前在B-Tree中使用的总空间
12.PCT_USED :B-Tree正在使用空间的百分比
13.当前索引的高度为3,分配给segment的block为59392,对应的叶子块数量为58824,枝块数量为89 ,空间分配达到了449M,使用空间占比达到了90%


注意:coalesce产生了大量redo size

注意:
1.HEIGHT :B-Tree索引高度
2.BLOCKS :分配给段的块
3.LF_BLKS :B-Tree的叶子块数量
4.LF_ROWS_LEN :所有叶行长度的总和
5.LF_BLK_LEN :叶块中的可用空间
6.BR_BLKS :B-Tree中分支块的数量
7.BR_ROWS :B-Tree中的分支块长度
8.BR_ROWS_LEN :B-Tree中所有分支块长度之和
9.BR_BLK_LEN :分支块中的可用空间
10.BTREE_SPACE :当前B-Tree分配的总空间
11.USED_SPACE :当前在B-Tree中使用的总空间
12.PCT_USED :B-Tree正在使用空间的百分比
13.没经过coalesce合并操作之前的各项指标为:索引的高度为3,分配给segment的block为59392,对应的叶子块数量为58824,枝块数量为89 ,空间分配达到了449M,使用空间占比达到了90%
14.经过coalesce合并后的各项指标为:索引的高度为3,分配给segment的block为59392,对应的叶子块数量为39248,枝块数量为89 ,空间分配下降到300M,使用空间占比仍然为90%,对应索引使用的总空间由原来的401M下降到267M



----- end tree dump
注意:
1.经过coalesce后的Leaf Blocks是39248, 第一个记录是索引的root块,下面若干条记录为leaf block的指标信息, 主要的指标包括两部分:1.索引条目的数量nrow,2.实际的索引条目的数量rrro2) status:no-deleted这两项指标表示方法就是row:17.17的方式
2. leaf block的nrow,rrow 变成了 row:nrow.rrow 合并成了一列, avs表示leaf blocks的可用空间
1.3我们随便dump一个数据块结构:


注意:
1.每个索引块(分支或叶子)都有一个共同的结构和一些附加信息,这取决于它是叶子还是分支块。其中kdxco(为公共索引核心调用堆践)的常见结构为 defind,kdx3 h,
2.kdxcolev, b树中级别的最大数量为24(0-23),一个24级索引,每个索引块有2行,可以容纳2*(3**23)~ 188亿个叶子行。










注意:
1.针对非唯一索引,当我们将rowid存储为索引键的另一列每个列都有长度和数据对
2.Kdxledsz是0,当行数为0时,行索引中的第一个条目是有效的,并指向从块中删除的最后一行。
3.从上面的trace文件中可以看到允许一个空的叶子块位于搜索树中
4.针对唯一索引Kdxledsize是6,这里不做演示了
总结:
1.经过coalesce后,索引的leaf block明显减少,对应索引结构实际占用空间有所下降。
2.coalesce带来的redo size开销并不小,刚才的一笔coalesce操作就产生了763M的redo size ,不建议在生产环境业务繁忙期间对大表操作。
3.branch枝块和root根块的结构是不会变化的,同时coalesc命令并不释放索引上的多余空间
4.我们通过dump btreedump,block dump两种方式,扩展说明了coalesce的数据库块变化情况,索引结构情况,帮助大家更深入的理解
2.接下来我们来看看shrink操作带来的性能影响,我们先把上一个步骤的索引结构粘贴下来,方便查看
2.1复制上一部分索引结构内容:

注意:
1.HEIGHT :B-Tree索引高度
2.BLOCKS :分配给段的块
3.LF_BLKS :B-Tree的叶子块数量
4.LF_ROWS_LEN :所有叶行长度的总和
5.LF_BLK_LEN :叶块中的可用空间
6.BR_BLKS :B-Tree中分支块的数量
7.BR_ROWS :B-Tree中的分支块长度
8.BR_ROWS_LEN :B-Tree中所有分支块长度之和
9.BR_BLK_LEN :分支块中的可用空间
10.BTREE_SPACE :当前B-Tree分配的总空间
11.USED_SPACE :当前在B-Tree中使用的总空间
12.PCT_USED :B-Tree正在使用空间的百分比
13.当前索引的高度为3,分配给segment的block为59392,对应的叶子块数量为58824,枝块数量为89 ,空间分配达到了449M,使用空间占比达到了90%
2.2初始化操作:




注意:shrink space过程中产生了TM表级锁和TX独占行级锁


3.自由空间碎片FSFI值
3.1当表上发生大量DML操作时,由于DML不会从HWM下的表释放空闲空间,因此表将变得支离破碎。因此,尽管行数更少,但由于碎片化,它会消耗更多
的空间。因此,最好定期重新组织oracle的堆组织表,这里通过一个案例帮助大家定位具体问题:
3.2我们来关注一个测试表的数量和segment物理存储空间分配情况:

3.3我们来看一下该表空间碎片的详细信息:


3.4我们梳理一个指标清单,帮助大家更了解自由空间分配情况的具体信息:
segment_owner Schema name of the segment to be analyzed
segment_name Name of the segment to be analyzed
partition_name Partition name of the segment to be analyzed
segment_type Type of the segment to be analyzed (TABLE, INDEX, or CLUSTER)
unformatted_blocks Total number of blocks that are unformatted
unformatted bytes Total number of bytes that are unformatted
fs1_blocks Number of blocks that has at least 0 to 25% free space
fs1_bytes Number of bytes that has at least 0 to 25% free space
fs2_blocks Number of blocks that has at least 25 to 50% free space
fs2_bytes Number of bytes that has at least 25 to 50% free space
fs3_blocks Number of blocks that has at least 50 to 75% free space
fs3_bytes Number of bytes that has at least 50 to 75% free space
fs4_blocks Number of blocks that has at least 75 to 100% free space
fs4_bytes Number of bytes that has at least 75 to 100% free space
ful1_blocks Total number of blocks that are full in the segment
full_bytes Total number of bytes that are full in the segment
/
注意:
1.我们可以看到该测试表,segment中已经full的总大小是20584bytes
2.75%-100%空闲的block是239
3.4我们尝试删除该测试表:

3.5检查物理segment分配情况:

3.6我们在跑一次查询脚本:


注意:
1.由于碎片造成的75%到100%的空闲空间的字节数达到了20825
3.6我们尝试去move操作:

3.8空间确实得到释放了,我们再次验证碎片检查脚本:


注意:
1.FSFI指向的空间碎片均已回收完毕
2.如果表上有索引,想着重建索引
3.未格式化的数据块也已经消失
4.在线重定义进行碎片整理的办法:
4.1检查t_600_demo是否具有按主键进行Online Redefinition能力

4.2创建一张与soctt.t_600_demo同结构的临时表scott.t_600_demo_bak

4.3对scott用户t_600_demo表启动Online Redefinition

4.4复制该表的索引、限制、触发器等依赖对象

4.5检查是否有除Primary、constraints之外的错误

4.6手工同步数据,该步骤为可选操作

4.7完成Online Redefinition操作

5.以下提供多种问题定位脚本:
5.1基于表空间计算Free Space Fragmentation Index(FSFI)

注意:如果FSFI值 < 30%,那么该表空间的碎片可能较为严重
5.2按表空间显示连续的空闲空间,以下脚本oracle MOS官方提供:






注意:以上脚本的执行结果验证标准为:一个表空间的extent数量越多,并且extent都比较小,则该表空间碎片现象比较严重
5.3基于统计信息进行碎片评估方法:


5.4基于blevel评估索引碎片:

注意:
1.上述语句将显示索引高度Blevel >=3,并且索引大小超过100M的索引。
2.第一个章节我们介绍过了analyze index XXX validate structure;
3.以及通过select DEL_LF_ROWS * 100 decode(LF_ROWS, 0, 1, LF_ROWS) PCT_DELETED from index_stats;定位问题的办法
4.通常来讲上述语句中PCT_DELETED的含义为索引被删除项与索引项总数的所占比例,如果PCT_DELETED>=20%,则说明该索引碎片严重。
5.analyze语句会对被分析索引产生锁,在生产系统运行会产生一定影响,因此我们建议优先考虑按BLEVEL分析方法
5.5段顾问的方法详见600群内文档,这里就不做演示了
<点亮梦想.拒绝平庸>
600团队(qq群:851604218)




