对一个千万级、大小16G的数据表进行在线分区
上一篇 /
下一篇 2007-08-09 00:00:00
/ 个人分类:管理
问题描述:
一个记录日志的表,当初没怎么考虑,结果现在日志表越来越大,占用空间达到16G,而里面的日志其实只需要保留一个月内的备查就可以了。于是想把此表改造成按月的分区表,这样到时候只要直接删除一个分区就可以了。
这是一个很特殊的案例,其实改造成分区表并在以后直接删除分区的目的是为了减少删除数据的时候归档日志的产生。但是怎么把这个表改造成分区表。
方案一:是直接创建一个分区表,相关的索引、约束等都建好,然后使用两个rename table name的命令去对表进行重命名,这个过程中可能会碰到有人正在使用老的表,那么会报resource busy的错误,没关系,多试几次就成功了。当然如果你把老的表rename过去了,新的表还没有rename过来的瞬间,如果有人在使用这个表,会报表不存在的错误,但是这个时间很短的,一般都在秒级别的,最多也就是几秒钟。如果你的业务允许,推荐使用这种方式,做完了直接把老的表的数据保存一段时间,然后直接drop掉。
方案二:使用oracle提供的在线重定义进行在线分区。这里不对在线分区进行过多的介绍,介绍此次进行在线重定义的操作过程。
在线重定义一个表,一般要分为一下几步:
1、使用DBMS_REDEFINITION.CAN_REDEF_TABLE来判断此表是否可以被在线重定义(因为在线重定义有N多限制的),这个过程有三个参数,其中关键的是options_flag参数,此参数有dbms_redefinition.cons_use_pk和dbms_redefinition.cons_use_rowid两个选项,分别是判断这个表是否可以使用主键或者使用rowid来进行重定义。推荐使用主键进行,此表没有主键,只能使用rowid。命令如下:exec DBMS_REDEFINITION.CAN_REDEF_TABLE('xxx','log',dbms_redefinition.cons_use_rowid);
2、创建一个分区表作为在线重定义的临时表,脚本忽略。
3、使用DBMS_REDEFINITION.START_REDEF_TABLE进行源表和中间表的数据复制,这个过程是最耗时间和资源的,这个过程产生了19G的归档,消耗了将近5个小时。或许,使用并行能够加快这里的数据复制的过程,但是需要在线重定义的,一般都是繁忙的生产系统,开了并行估计更恐怖。脚本如下:exec DBMS_REDEFINITION.START_REDEF_TABLE(uname=>'xxx', orig_table=>'log',int_table=>'log_t',options_flag=>dbms_redefinition.cons_use_rowid);
4、使用DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS来拷贝源表的各种约束,因为此表上有三个索引,而且索引还是建立在长度比较大的列上,这个过程产生了4G的归档,并消耗了两个小时的时间。脚本如下:exec DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(uname=>'xxx',orig_table=>'log',int_table=>'log_t',copy_indexes=>dbms_redefinition.cons_orig_params,copy_triggers=>true,copy_constraints=>true,copy_privileges=>true,ignore_errors=>false,copy_statistics=>true);
5、使用DBMS_REDEFINITION.SYNC_INTERIM_TABLE进行数据的同步,此步骤只需要同步的是以上操作期间产生的少量的数据,此过程可以运行多次,已使得最后切换的时候需要的时间最短。脚本如下:exec DBMS_REDEFINITION.SYNC_INTERIM_TABLE('xxx', 'log','log_t');
6、使用DBMS_REDEFINITION.FINISH_REDEF_TABLE进行最后的切换,这里是最关键的一步,这步我的感觉应该是先锁表,然后执行5中的同步,然后对表名进行rename。这个步骤花费时间长短是最关键的地方,此次测试消耗时间为5.8秒,还是比较的长。脚本如下:exec DBMS_REDEFINITION.FINISH_REDEF_TABLE('xxx', 'log','log_t');
到此为止,在线分区完成,一共花费了了23G的归档,7个小时的时间,和锁表将近6秒钟的代价。中间也想过,自己先lock住table,然后在进行两个rename操作,但试验中发现在lock住table并把它进行rename操作的时候,rename操作成功时对这个表的lock也就消失了,这时如果马上有人使用到这个表,还是会报表不存在的错误的。
不知道oracle怎么能不让它报错的,如果找到它的实现方法,用它的方法锁住表,然后直接rename,只要这中间使用这个表不报错而是锁等待,对于这种日志表的处理来说,这个方案就完美了!
总结:斧头有斧头的用处,刀有刀的用处,拳头也是凶器,就看你怎么在合适的场合使用最恰当的工具了。
导入论坛
引用链接
收藏
分享给好友
推荐到圈子
管理
举报
TAG: