最近应用中遇到一个大报表的导出,这个明细报表涉及的两个数据库表原始数据量超过300万条数据,过滤后报表取出数据量还有200万条左右。我们用分页的方法搞定了报表展现,但用户还需要将报表数据导出(他们要拷到硬盘寄出,而且是每月的固定操作),只能硬着头皮从oracle里取。


Oracle JDBC很慢,200万条的数据大概需要67分钟,可以预先放在调度器里晚上算,或者算的时候上个厕所抽根烟,但有时候领导着急要就显得时间过于漫长了。


后来用集算器的并行机制处理,多个JDBC连接同时取,把取数时间降到了几十秒。


系统软硬件配置:HP ProLiant DL380 G7, CPU Intel Xeon E5620*2, RAM 20G, HDD Raid5 1T

软件:Oracle11g64位,集算器,CentOS 6.0JDK 1.6u43

两表数据量:VM10w, 168cols,过滤后6.5w rows

        CT300w,16cols,过滤后195w rows


过程:查询两表的记录数,根据子任务数进行数据分段,指定子程序查询的数据范围,然后由callx调用子程序完成查询过程,最后主程序进行结果合并并生成最终返回给报表的结果集。


脚本:

主程序

从Oracle JDBC中取百万条数据的解决办法_并行

子程序:

从Oracle JDBC中取百万条数据的解决办法_oracel_02


从结果看,不并行的时候花了436秒(7分多钟),4个、8个、16个并行的时候,计算时间分别是113秒(不到2分钟)、81秒(1分多)、43秒。


16个并发的时候计算时间有了数量级的提升,爽!


需要注意的是使用并行取数需要子任务分别建立数据库连接,像我的子程序脚本中需要connect(conn)另外并行取数适用oracle资源比较空闲(如连接数未达上线)的情况,可以充分利用数据库资源。