0

我需要使用 Java 程序将大量数据(近 1000 万条记录)从一个数据库(oracle)传输到另一个数据库(postgres)。我通过创建与两个数据库的连接并从源数据库查询数据然后通过迭代结果集将数据插入目标数据库来完成相同的操作。但是传输数据需要大量时间。有什么方法可以快速完成转移过程?

4

3 回答 3

1

一种替代方法是将表中的所有数据导出到文本文件中,然后将该数据直接导入 postgres。我不记得 oracle 有什么导出功能,但最坏的情况是你总是可以使用这样的查询,将表的内容作为一组插入语句转储:

select '插入 mynewtable 值(' || old.a || ', ' || old.b || ...etc..|| ');' 来自 myoldtable old;

我肯定在几个小时内处理了来自 Oracle 数据库(使用 Java)的 10MM 记录(每条记录之间有很多处理)。你希望什么样的表现,你现在得到什么?

当您插入 postgres 表时,您是否检查了很多索引或约束?也许您的代码有其他问题?如果您知道所有行都是有效的,也许您应该在进行插入时删除 postgres 数据库中的约束?

或者,如果您有一段时间没有,也许您需要清理数据库?

于 2012-05-10T10:16:20.800 回答
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 中完成命名管道的事情,所以需要研究一下,但这应该能让你继续前进。

你需要弄清楚你的瓶颈在哪里。我已经看到性能随着时间的推移而下降,因为查询是对某个表进行表扫描,并且检索后面行的数据比前面的行需要更长的时间。

与其他任何事情一样,您需要开始引入计时,以查看您的选择是否开始花费更多时间,或者读取性能是否相当稳定(如果后面的行获取时间比前面的行获取时间长,这是一个很好的表扫描指示)。

最后,如果您可以巧妙地分解查询,您可以使用多个工作线程来并行处理数据。

IE。代替

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;

像其他任何事情一样,有一百种做事的方法。

于 2012-05-10T15:33:07.710 回答
0

这里的问题是编程语言使用游标来处理元组集,游标只能遍历它们,你不能进行批量加载或类似的事情,我认为每种编程语言都是如此,更快的解决方案是以某种方式将 Oracle 连接到 PostgreSQL ,我不知道该怎么做,但我认为应该是可能的。一切都有 Oracle 函数。

于 2012-05-10T09:51:46.700 回答