0
点赞
收藏
分享

微信扫一扫

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较

索引rebuild和coalesce操作的比较

虽然大多数情况下,我们并不需要重建索引,来回收索引中的碎片空间,让索引的访问更高效。但是,对于一些特定的情况,比如有较多且较大空闲空间的叶子块,且很少有适合的索引条目被插入,可能导致大量空间浪费;或者经历了一次大量数据的删除后,希望减少因此而导致的索引访问效率不佳的问题,而需要重建索引时。我们通常会有两种重建索引的方法:alter index xxx rebuild和alter index xxx coalesce。

Rebuild的方式,加排它锁,会让单个索引块内的可用空间尽可能少,整个索引所需的索引块更少,高度更低。通常,在索引中的碎片空间超过三分之一时,Rebuild期间产生的REDO更少,但它需要额外的临时空间以完成这一操作。

Coalesce的方式,无排它锁,仅在叶子块层级做合并,不会降低索引高度,但会减少叶子块的数量。通常,在索引中的碎片空间低于三分之一时,coalesce期间产生的REDO会更少,且操作期间不需要额外的临时空间。

下面,我们还是通过实验,来观察一下这两种重建索引的方式的主要差异:

我们使用类似误区1中的实验环境创建方法,创建一个三层的索引:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_b-tree


图 165

查看该索引的树形结构信息:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_rebuild_02


图 166

如上图所示,我们可以看到该索引是一个三层高的索引。主要叶子节点都集中在第一个分支块上。第一个分支块下有16个叶子块,每个叶子块中有13条索引条目。

1 无碎片空间时两种重建方式的对比

接下来,我们在索引中并没有所谓“碎片”空间的情况下,分别用rebuild和coalesce的方法重建该索引,观察相关操作消耗的资源开销(逻辑读,REDO和UNDO)。

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_索引_03


图 167

如上图所示,使用REBUILD方式时,其逻辑读的消耗是289(1228-939)块次,REDO的产生量是175444(494756-319312)字节,UNDO的产生量是4528(17852-13324)字节。

再来看看REBUILD后,索引的结构是否有了变化呢?

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_rebuild_04


图 168

如上图所示,索引的结构没有变化,依然是三层,2个分支块,17个叶子块,其中16个叶子块在第一个分支块上。但是,我们可以发现,所有的索引块都已经和之前的,没有一个是重复的。即,REBUILD方式,是在另一块存储空间,把原索引重建了一遍。

我们再来看一下使用COALESCE方式时,其表现又是什么样子。

为了避免干扰,我们重新创建相关索引,并使用COALESCE的方式来操作。

此时新建的索引树形结构信息如下:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_b-tree_05


图 169

我们进行COALESCE的操作,并查看其资源开销:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_rebuild_06


图 170

如上图所示,使用COALESCE方式时,其逻辑读的消耗是38(156-118)块次,REDO的产生量是1076(5400-4324)字节,UNDO的产生量是80(536-456)字节。明显比REBUILD的开销要小。

继续查看COALESCE处理后,其索引的树形结构信息:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_coalesce_07


图 171

我们可以看到COALESCE操作前后,索引块的编号及其在索引中的位置是一模一样的。没有变化。

2 30%碎片空间时两种重建方式的对比

下面,我们尝试模拟索引中有约30%的索引条目被删除后,用不同的重建方式,其资源开销的情况:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_b-tree_08


图 172

如上图所示,使用REBUILD方式时,其逻辑读的消耗是243(787-544)块次,REDO的产生量是120624(223580-102956)字节,UNDO的产生量是4104(81624-77520)字节。

此时,索引的树形结构信息如下:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_coalesce_09


图 173

如上图所示,索引目前变为了2层的高度。只有1个根块和12个叶子块了。

再来看下COALESCE方式。重建相关索引,并删除30%的记录:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_rebuild_10


图 174

进行COALESCE的操作,并是查看相关开销:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_索引_11


图 175

如上图所示,使用COALESCE方式时,其逻辑读的消耗是143(2287-2154)块次,REDO的产生量是230380(878116-647736)字节,UNDO的产生量是138460(314320-175860)字节。

此时,索引的树形结构信息如下:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_b-tree_12


图 176

如上图所示,索引的高度没变,分支块没有减少。但第一个分支块下的叶子块,由删除前的16个叶子块,变为12个叶子块。

3 60%碎片空间时两种重建方式的对比

重建表和索引,并删除其中约60%的索引后,观察REBUILD方式的开销:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_rebuild_13


图 177

查看REBUILD方式的资源开销:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_rebuild_14


图 178

如上图所示,使用REBUILD方式时,其逻辑读的消耗是238(4171-3933)块次,REDO的产生量是76896(14772244-1395348)字节,UNDO的产生量是4104(488428-484324)字节。

此时,索引的树形结构信息如下:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_索引_15


图 179

如上所示,索引变为了2层高,叶子块减少到7个。

同前,再次重建表和索引,并删除其中约60%的索引后,观察COALESCE方式的开销:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_coalesce_16


图 180

如上图所示,使用COALESCE方式时,其逻辑读的消耗是194(4171-3933)块次,REDO的产生量是268260(1244492-976232)字节,UNDO的产生量是180716(684516-503800)字节。

此时,索引的树形结构信息如下:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_索引_17


图 181

如上图所示,索引的高度没有变化,依然是3层,但叶子块减少了。

4 总结

我们将三种情形下的两种重建方式的资源开销和索引层高的变化,汇总到如下表格中:

Oracle中B-tree索引的访问方法(十四)-- 索引rebuild和coalesce操作的比较_b-tree_18


如上表所示,我们可以发现如下规律:

  1. 从逻辑读(logical reads)上来看,对于REBUILD方式,无碎片时最多,碎片越多,逻辑读越小。其原因应是重建后的索引需要的索引块越来越少所致;对于COALESCE方式,逻辑读正好相反,无碎片时最小,碎片越多,逻辑读越多。其原因应是碎片越多,需要处理的块越多所致。
  2. 从redo size上来看,对于REBUILD方式,无碎片时最多,碎片越多,redo size越小。其原因也应是重建后的索引需要的索引块越来越少所致,即修改的量在不断减少;对于COALESCE方式,redo size正好相反,无碎片时最小,碎片越多,逻辑读越多。其原因也应是碎片越多,需要修改的块越多所致。
  3. 从undo size上来看,对于REBUILD方式,无论碎片多少,其消耗基本持平。其原因应是新索引是向新块中插入数据,所以,需要的UNDO量很少。而对于COALESCE方式,undo sizer的消耗与碎片的多少成比,碎片越多,undo size越多。其原因也应是碎片越多,需要处理的块越多所致。

综上,从资源开销上说,当碎片较小时,使用COALESCE会消耗更少,而当碎片不断增加,COALESCE的开销会越来越大;而REBUILD方式则正相反,碎片越多,其需要的资源会越来越小。
此外,从索引层高上,我们也会现,REBUILD是重新紧密排列索引,会导致索引高度降低;而COALESCE则只在叶子块层重新紧密排列,并不会导致索引高度降低。因此,对于表中的数据大量减少后,又会很快增加记录的表,使用COALESCE的方式重建索引,会减少分支和根块的分裂次数,有利于减少争用。但此情况时,因为删除了大量数据,索引中的碎片必然较多,使用COALESCE会导致操作期间的资源开销较大。如果表中的数据大量减少后,数据增加得较慢,那么使用REBUILD方式来重建索引时,开销会比较少,同时由于增长较慢,索引的分裂导致的负面影响也会相对轻得多。至于用哪一种方式更好,则需要根据具体需求和环境条件来做出最终的选择。

举报

相关推荐

0 条评论