ITPub博客

大分区表的手工并行优化

原创 Oracle 作者:jeanron100 时间:2013-11-08 20:00:57 0 删除 编辑
这段时间饱受大分区表的性能之苦,碰到最大的一个分区表有1个t左右,操作起来每个细节都需要格外小心,我这次和大家分享的案例应用的分区表不是很大,有80G左右。但是这个分区主要分区比较多,有将近2000个左右的分区。
举一个案例来说明一下。
现在要做以下下几件事,要保证要宕机时间尽可能短。
为了方便起见,我暂定现在有4个DB instance,叫par01,par02,par03,par04.
1.需要对par01的数据运行Update语句,根据条件更新(update操作可能会移动分区),
2.然后把par01的数据导出来
3.重新对par01,par02,par03,par04进行分区
4.选择性的把数据导入到par01,par02,par03,par04
所以看以上步骤最终目的就是把par01的数据更新以后重新分布到par01,par02,par03,par04上去。
除了以上的4个步骤,我还设想了以下的实现方式,但是实际操作的时候,发现不好控制,而且可能在网络带宽和磁盘空间上都有一定的要求。
1)采用db link,在par01上建立par02,03,04的db link,然后对Par01,02,03,04分区后,数据的复制直接使用db link来做。-->这个部分对网络带宽有很高的要求,而且比较纠结的一点事不好控制进度。如果有任何异常,只能重新开始。
2)采用临时表,建立4个临时表,设置为Nologging,然后使用insert/*+append */的方式根据需要插入数据。然后导出,然后重新导入到02,03,04上。->-会占有大量的磁盘空间,相当于复制了一份数据的镜像。比如库有200G,就得额外需要200G的数据空间。需要耗费更长的时间。


首先是第一个部分。
1.需要把par01的数据运行Update若干语句(update操作可能会移动分区),
这种update操作对于oracle来说是敏感的。
需要enable row movement才可以。
因为备份已经充足,所以特意对表设置了nologging.
然后按照开发提供的脚本运行update,(有奖金8个sql语句)结果update整整跑了快6个小时。幸亏是测试环境预演,能够提前发现很多的问题。
可以接受的时间范围是30分钟左右。所以只能想办法最大限度的压缩时间。
首先能想到的是parallel,但是通过测试 parallel dml也有诸多限制,而且效果也不明显。
最后采用的方法是:par01有上千个partition,可以把每个partition看成独立的一张表,然后对每个Partition来执行相应的Update,然后在此基础上根据High_value进行划分,来决定采用多少个个窗口并行的去跑Update。
sql语句大体如下
update test partition(parxxxxx) set  xxxx where xxxxx;
最后根据数据情况和High value我开了5个窗口并行的跑update,效果很明显。最后跑了将近半个小时,中间根据一定的频率来commit,性能确实提高了不少。

2.然后把par01的数据导出来,
大家对于数据导入导出,首先都是expdp/impdp,但是在这个场景里,不太妥当,而且有一定的风险,最后决定使用exp/imp
原因如下:
1.我们所用的库是从10.2.0.5.0手工升级到11.2.0.2.0的。对于expdp/impdp有一些已知11g的bug提到会导致数据泵hang住。
2.par01,par02,par03,par04的网络环境很好,如果使用expdp/impdp需要配置相应的directory和用户权限,而且需要把dump文件拷贝到各个服务端目录下,需要耗费大量的时间,而且拷贝80多G的dump文件也需要准备足够的空间。如果直接在par01上进行导入,不需要配置,就方便度多了。
3.导出需要生成几个独立的dump文件。采用的方法如下。
exp xxxx file=par01_xxxxxx.dmp log=par01_xxxxx.log statistics=none grants=n constraints=n indexes=n tables=xxxx query=\"where code in \(xxx,xxx,xxx\)\" buffer=9102000
expdp在这种情况下没有明显的优势,首先query选项启用,direct就没作用了,开了并行,等了好一会,貌似Hang住了,
最后采用的方法是:采用导出分区的方式,根据数据量和业务情况,把导出工作分成5个单独的进程来跑,每个进程会导出指定的分区
比如  thread1:分区par_001~par_005
       thread2:分区par_100~par_105
查看系统的负载,导出时cpu都是满载的,效果应该和expdp的并行效果差不多,但是控制要灵活。
最后统计结果,本来需要100分钟以上的任务,最后用了将近30分钟就全部导完了。

3.重新对par01,par02,par03,par04进行分区
需要对Par01,02,03,04的分区进行重新的组织。比如原来表只有100个可能根据需要得分成200个分区了,而且分区名称也有要求。

这个地方可能有两种实现,
一种是把分区都drop掉,只留一个max pattition,然后split partition
另一种方法是把分区不断的进行merge,最后合并成一个max parition.
我最终选用的是第一种方法,因为比较直观简单,重新分区的时候步骤很有规律,我生成了动态sql来删除分区,只保留默认的max partition.
这个部分多说一句,有的朋友可能建议不删数据了,直接根据需要split partition,生成指定的分区,我尝试了这种方法,速度太慢。可能有大量的数据会从各个partition间不断的move>

4.选择性的把数据导入到par01,par02,par03,par04
这个部分基于步骤2,独立的导入,时间也好控制。
比如说par02这个分区比较大,我导出的时候就生成了两个dump文件,然后导入的时候,就可以在par02上分两个独立的导入进程操作。

以上是自己的一些总结。也对比了一些其他优化的案例。有些不足,还希望大家多多指教。



来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/23718752/viewspace-776144/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
技术文章每天更新,阵地已转移到微信公众号端。 公众号:jianrong-notes

注册时间:2012-05-14

  • 博文量
    1667
  • 访问量
    14215504