从oracle数据里向外迁移大量数据,有多种方法。其中一种就是应用jdbc连接oracle,写代码向外分页提取。我现在工作的一个任务就是从oracle中单表数据提取出来,进行单行数据加工转换,然后再写入MysqL中。我所用的工具是spring batch。原来的方案是通过生成sql语句,直接导入MysqL中,但是这个数据转换业务太复杂,所以就采用了前面的方案。
spring batch 对于数据进行批处理,主要分三步:
- 从源库oracle 中读取数据(ItemReader);
- 对于读取数据进行处理(ItemProcessor);
- 处理结果写入目标库MysqL (ItemWriter);
本文不讲如何应用spring batch 的具体步骤,只讲如何在oracle中如何进行分页提取。从oracle中读取数据,如果数据量不大,我们可以一次性直接取出,然后根据业务规则处理后续步骤。但是当数据量大到一定程度,就不能一次取出那么多数据,不然后果自负。那么如何进行分而获取呢?
之前所用的sql分页语句(方案A):
select * from ( select rownum rownum_,t1.* FROM (我的查询语句) t1 ) t2 where t2.rownum_>? and t2.rownum_ <=?
一直也没有太在意它的好与坏。但是这次导数据,被始的时候从oracle中提取数据很快,可是越到后面提取的时间越长。这让我不得其解,所以就怀疑这个sql的性能。后来将其改为(方案B):
select * from ( select rownum rownum_,t1.* FROM ( 我的查询语句 ) t1 where rownum<=? ) t2 where t2.rownum_>?
速度就上去,方案B的性能好与方案A,所以大家不要用方案A,要采用方案B。
那么这篇文档,就这样结束了有点对不起标题--深入理解。这根本就不深入吗?那么如何才算深入呢?搞清楚方案B为什么比方案A高效,这样才算深入。其实这个问题,ThomasKyte 已经解释过了,在一本叫《oracle高效设计》中第8章第3节: 用ROWNUM标记页号。但是这样书目前来看已失传了,原因是它老了讲oracle 8版本的。还有年代久远,tom也不再出新版了,所以被遗忘了。刚才我在百度上还能搜索到这本书的下载链接,所以有兴趣的朋友可以下载看一下。
小插曲: 背景:关于这本书是没得买了,我不太爱看电子书,大约2年前就把第8章、第9章打印出来了,看了之后也没有装订,就散放在书架上的。 现在:我也是偶然间看到这个解决方案的,之前因为程序出现性能问题,很郁闷的下班回家,路上一起在思考这个问题,如何才能解决它的性能呢?可是回到家吃过了晚饭,关于这个问题也没有找到答案。家里有一个2岁的熊孩子,只要见到笔,那就要纸(之前我跟我妈说了,纸给他玩没事,书就别给他涂了),然后他的作品就这样产生了,纸散落的到处都是。吃过饭了,帮他收拾烂摊子的时候,偶然捡到这张A4纸正好是关于ROWNUM的,于是就细细的再读读这一段,第二天改了代码一切都ok了。所以家里有个熊孩子或萌娃子也不错,他会把你所有的所有的东西都会帮你找出来晒晒,哈哈!谢谢熊孩子!