海量数据迁移之分区表批量insert性能改进

在平时的工作中接触到的分区表一般都比较大,而且分区也少则几十,多则几百,上千。
在数据迁移的时候,分区表的迁移更是块大骨头,因为数据量太大,而且有些分区表中还有一些lob字段,想直接通过sqlldr来迁移还是需要做一些额外的工作。
如果通过datapump分区导出数据,批量导入,也是一种思路,不过需要考虑好并发的进程。
通过oracle_datapump来做数据的导入,可能更为灵活,但是不是绝对的。最近就做了一些相关的数据导入测试,感触不少。

比如,目前我们需要导入的两个大表,一个是memo,一个是charge,分区都有200多个。
而且数据分布不是很均匀。有的分区可能数据要多很多。使用oracle_datapump抽取的时候,比如memo表有25G,如果按照100M为一个单位,那么就要生成250个dump 文件。每个dump文件中大概有50多万条数据,抽取的dump文件不是基于分区的。然后在目标库中以外部表的形式加载,然后使用insert来做数据插入,启用8个并行度。导入的时候速度就不是很理想。平均每个dump文件需要大约1~2分钟的时间,甚至更长。就算减少并行度,控制在4左右,速度还是没有什么变化。
本来冥思苦想的这个方案性能打了折扣,然后再一次尝试,限制生成的dump文件个数,比如memo表有25G,生成80个dump,这样每个dump文件就有将近300M左右。这样每个dump文件就大概由150万的数据。还是启用了同样的并行,速度就会快很多,一个dump文件大约在1~2分钟,dump的个数少了大半,时间就随之节省了很多。

基于这个问题,我的想法是dump在100M左右的时候,启用并行不会有什么大的起色,启用8个4个,应该和不启用并行效果是类似的。
如果dump文件大了很多,如果启用并行,就会有相应的进程能够合理的处理一部分数据。
同时,因为memo表是分区表,如果做insert插入的时候,一个insert会在每个分区上加一个锁,这样就是200个多锁,这个也是很消耗资源的。如果频繁的做插入,commit动作,就会不断的去加同样数量级的锁,无形中也快拖累加载速度。如果dump文件较大,还是会加同样的锁,但是会在一定程度上使得并行使用的更为充分。可能加锁的频率降低了,对系统的负载也会小很多。

如果想有较大的改进的话,我的个人想法就是通过分区级别导出数据,然后在数据插入的时候,也是基于分区导入,这样就可以同时做多个insert操作,而且每个insert只会锁定一个相应的分区。而且考虑加入并行,可能性会好很多。
按照这个思路,就没有严格意义上的大表了,我们都可以切分再切分。

上一篇:视频聊天创企Tribe获300万美元种子轮融资


下一篇:iOS:iPad和iPhone开发的异同(UIPopoverController、UISplitViewController)