我需要使用Java程序将大量数据(近1000万条记录)从一个数据库(oracle)传输到另一个数据库(postgres)。我通过创建与两个DB的连接并从源数据库查询数据然后通过迭代结果集将数据插入目标数据库来完成相同的操作。但这需要花费大量时间来传输数据。有没有办法快速完成转移过程?
答案 0 :(得分:1)
一种替代方法是将表中的所有数据导出到文本文件中,然后将该数据直接导入postgres。我不记得oracle有什么导出功能,但最糟糕的情况是你总是可以使用这样的查询,将表的内容作为一组insert语句转储:
选择'插入mynewtable值('|| old.a ||','|| old.b || ... etc .. ||');'来自myoldtable old;
我确实在几个小时的时间内从Oracle数据库(使用Java)处理了10MM记录(每个记录之间进行了大量处理)。你希望什么样的表现以及你现在得到什么?
在插入postgres表时,是否检查了很多索引或约束?你的代码可能还有其他问题吗?如果你知道所有的行都是有效的,也许你应该在插入时删除postgres db中的约束?
或者,如果您暂时没有,也许您需要清空数据库?
答案 1 :(得分:1)
如果您仅限于单线程读取数据,写入数据,那么就没有很大的改进空间。
这种类型的性能受到一些不同的限制,即您在线路上移动的数据量,网络速度,数据库索引和配置以及网络/主机中的其他一些内容。
至少应该使用更大的fetchsize设置读取连接。
ResultSet rs;
...
rs.setFetchSize(500);
在插入方面,您还应该查看使用CallableStatement
进行批处理CallableStatement cs;
Connection conn;
conn.setAutoCommit(false);
...
cs.addBatch();
if (rowCount % batchsize == 0) {
int[] updateCounts = cs.executeBatch();
conn.commit();
batchCount = 0;
for (int i = 0; i < updateCounts.length; i++) {
if (updateCounts[i] < 1)
bad.write(batchRec[i]);
}
}
您可以在Oracle中执行其他一些插入性能,其中一个是使用命名管道设置批量加载,然后您的进程可以写入该命名管道。它们是非记录操作,所以速度非常快。我还没有从Java那里完成命名管道的事情,所以这是值得研究的东西,但是这应该让你去。
您需要弄清楚瓶颈在哪里。我看到随着时间的推移性能下降,因为查询是在某些表上进行表扫描,并且检索后续行的数据需要更长的时间。
与其他任何东西一样,您需要开始引入计时,以查看您的选择是否开始花费更多时间或者读取性能是否相当稳定(如果后面的行提取需要比先前的行更长时间,那么表扫描的良好指示抓取)。
最后,如果您可以整齐地中断查询,则可以使用多个工作线程并行处理数据。
即。而不是
select a,b,c from source table
你可以将其分解为
select a,b,c from source table where a < 10;
select a,b,c from source_table where a >= 10 and a < 50;
select a,b,c from source_table where a >= 50;
与其他任何事情一样,有一百种方法可以做。
答案 2 :(得分:0)
这里的问题是编程语言使用游标来处理元组集,游标只能迭代它们你不能进行批量加载或类似的东西,这是真的,因为我认为每种编程语言,更快的解决方案都是连接Oracle以某种方式对PostgreSQL,我不知道该怎么做,但我认为它应该是可能的。一切都有Oracle功能。