2014-10-09 55 views
0

,所以我必须使用JDBC的Java代码使用事先准备好的声明,看起来有点像这样将数据插入到PostgreSQL数据库:如何测试,如果一个PreparedStatement将要耗尽内存

PreparedStatement statement = // prep statement 

for (int value: values) { 

    statement.setInt(1, value); 
    statement.addBatch(); 
} 

statement.executeBatch(); 

的问题是,我偶尔会碰到例外java.lang.OutOfMemoryError: Java heap space。我环顾四周,但我找不到任何东西;我如何测试语句即将耗尽内存,以便可以执行批处理。类似这样的:

PreparedStatement statement = // prep statement 

for (int value: values) { 

    statement.setInt(1, value); 
    statement.addBatch(); 

    if (statement.currentSize() + sizeof(int) > statement.mazSize()) { 

     statement.executeBatch(); 
    } 
} 

statement.executeBatch(); 

感谢您的任何帮助。

+0

您是否关闭了您创建的所有资源 - 准备好的语句,结果集等? – 2014-10-09 15:53:49

+0

当我批处理语句时,我看看内存消耗并在'%x == 0'后面刷新它们。你可以监视空闲的堆空间,但我只是懒得这样做。 – Hannes 2014-10-09 15:54:17

+0

使用较小的批量大小说500并迭代执行。 – 2014-10-09 15:55:51

回答

2

没有可靠的方法提前发现实例化是否会失败。

但是,更重要的是:您可能会错误地使用JDBC批处理工具,这会在插入多行时解决网络往返开销问题。大于100的批量大小显示收益递减,实际上可能导致放缓。

因此,将您的批处理策略更改为使用固定批量大小的小数字,两位数整数。

+0

在完全隔离的事务中写入10m条目,我发现,基于使用的db配置,在flush之前少于1k条目放慢了整个过程。 – Hannes 2014-10-09 15:58:48

+0

@hannes网络方面,数据库有多远?在任何合理的生产系统中,它都非常接近。往返时间越长,需要的批量就越大。 – 2014-10-09 16:01:33

+0

这只是一跳,但大量使用。这是我的第一个mariadb,所以我最终花时间调整了它。但是您的声明适用于db2,oracle和sqlserver。 – Hannes 2014-10-09 16:06:14