高效删除多碎片的字典管理表空间

on

在Oracle8i版本中,当一个字典管理(DMT)的表空间由于长期数据更新而产生大量碎片之后,通常我们的做法需要将原先放置在DMT表空间中的表move到本地管理(LMT)表空间来重组数据以减少空间碎片。move完毕以后,原先的DMT表空间需要删除以回收空间,但是删除表空间对于fet$的级联操作,导致删除DMT表空间非常耗费时间。

在字典管理类型下,fet$中存储数据库目前可以使用的空闲块信息,uet$存储数据库目前已经被使用的数据块信息。当删除表空间时,Oracle需要把fet$中跟此表空间相关的所有的记录都一一删除,如果表空间碎片很多,那么这一步操作将耗费很长的时间。

SQL>select ts#,count(*) from fet$ group by ts#;

TS# COUNT(*)
———- ———-
0 817
1 12160
3 440932
4 15775
5 5300
6 314997

6 rows selected.

在这个数据库中TS#=3和6的表空间正需要做删除的操作,而fet$中分别存在440932和314997条记录,在删除表空间时跟踪了一下,平均每秒钟Oracle能够清理fet$的3条记录。

SQL> select 440932/3/3600 from dual;

440932/3/3600
————-
40.827037

SQL> select 314997/3/3600 from dual;

314997/3/3600
————-
29.1663889

可以看到删除表空间3需要40个小时,而对于表空间6也需要29小时左右。当然,实际上,随着fet$表中记录的减少,Oracle的处理将会越来越快。当然,无论如何,这始终是一个很耗费时间的操作。

在某些情况下,这么长的时间可能是无法接受的,那么如何高速执行删除此类高碎片率的表空间呢?在itpub中有人提出了非常有效的方法-修改fet$基表,结合碎片

在itpub的这个例子中,因为需要删除的表空间中仍然还存在对象,所以操作起来需要更加小心谨慎,而对于一个已经move了所有对象的表空间,操作步骤更少。

1. 将fet$中所有属于需要drop的表空间中的数据文件的block#>2的记录全部删除
2. update这些数据文件的block#=2的记录,将length字段更新为blocks-1(blocks值可以从dba_data_files视图中获得)

可惜的是,由于是产品库,客户出于保险起见,最终没有同意这样的删除方法,少了一次实践的机会。

3 Comments Add yours

  1. 什么时候Oracle出一个Package来快速清理没有数据段的碎片表空间?

    期待啊~

  2. kamus says:

    没可能了吧,9i以后的LMT表空间已经不会再产生这样的碎片问题,fet$,uet$也一去不复返,8i早都不再被support,所以Oracle应该不会再有这样的package了。
    10g里面的shrink命令已经可以快速回缩没有使用到的table空间了。

  3. sopher says:

    我们单位的老库有的还在忍受随片的折磨。。。

Leave a Reply

Your email address will not be published. Required fields are marked *