如何测试PreparedStatement是否会耗尽内存

时间:2014-10-09 15:50:04

标签: java postgresql jdbc prepared-statement

所以我有一些使用JDBC的java代码,使用准备好的语句将数据插入PostgreSQL数据库,看起来有点像这样:

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();

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

没有可靠的方法可以事先找出实例化是否会失败。

然而,更重要的是:您可能滥用JDBC批处理工具,这可以解决插入多行时网络往返开销的问题。 100以上的批量大小显示收益递减,实际上可能导致减速。

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

答案 1 :(得分:0)

我遇到了与您的代码相似的问题,因为它假定输入数组/列表(values)的大小最大为三位数-这是在代码级别上由开发人员对其进行编码的一个假设有。

一天,数组/列表接近14k,此代码导致OOM,尽管有一件事我注意到数据已成功提交到DB(其Db2 + Oracle Weblogic设置),几秒钟后OOM,系统出现故障。

要解决此问题,我只是将statement.executeBatch();设置为预定的固定大小,如下所示,假设固定的批量大小为100,

int counter = 0;
for (int value: values) {
    statement.setInt(1, value);
    statement.addBatch();
    ++counter;
    if(counter >= 100 ){
     statement.executeBatch();
     counter =0;
   }
}
statement.executeBatch();

我不确定这是否也与驱动程序有关,但是我认为固定的批次数量将因设置的不同而有所不同(我有一个强大的多节点DB2集群,并且Web App是也位于同一数据中心),并且我测试了多种大小,并且1000的速度相当快,没有出现任何问题,但是我减小了大小,因为此代码是从在线UI应用程序中踢出的,因此同一代码可能有多个触发器。

我想这取决于这两者-一个可以保存在内存中的Statement对象的数量以及DB处理一个提交的批处理所花费的时间,因为代码将等待那么长时间。

相关问题