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

在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视图中获得) 可惜的是,由于是产品库,客户出于保险起见,最终没有同意这样的删除方法,少了一次实践的机会。