春季批处理JdbcCursorItemReader导致内存不足的问题

时间:2019-03-28 05:56:31

标签: java spring-batch

我正在使用Spring Batch框架进行数据迁移。我使用的阅读器是JdbcCursorItemReader。我将块大小设置为500,并将读取器读取大小设置为1000。但是,使用spring batch运行服务时,它似乎只读取一次内存中的所有数据,而用完了内存。然后抛出一个内存不足的问题。下面是我定义阅读器的方法:

   private JdbcCursorItemReader<Map<String, Object>> buildItemReader(final DataSource dataSource, String tableName,String tenant) {
        String tenantName = tenantHelper.determineTenant(tableName);
        JdbcCursorItemReader<Map<String, Object>> itemReader = new JdbcCursorItemReader<>();
        itemReader.setDataSource(dataSource);
        itemReader.setSql("select * from " + tableName + " where " + tenantName + " ='" + tenant + "'");
        itemReader.setRowMapper(new ColumnMapRowMapper());
        itemReader.setFetchSize(100);
        return itemReader;
    }

更重要的是,从spring批处理文档here中,我们应该能够通过使用jdbcCursorItemReader来避免内存问题

3 个答案:

答案 0 :(得分:2)

您可以尝试使用JdbcPagingItemReader代替JdbcCursorItemReader,在配置该页面时可以设置页面大小

答案 1 :(得分:1)

  

我只是感到困惑,为什么会使用所有内存并将所有数据加载到内存中

根据Postgresql's documentation,驱动程序会立即收集所有查询结果。

您可以尝试通过将获取大小设置为0来关闭光标。如上述文档所述,还有其他限制,请确保您的代码满足所有限制。仅供参考,这与MySQL可能发生的情况类似,在MySQL中,应将抓取大小设置为Integer.MIN_VALUE以流式传输结果(请参阅herehere)。

希望这会有所帮助。

答案 2 :(得分:1)

通过使用jdbcPagingItemReader解决了这一问题。游标读取器占用大量内存的根本原因是因为它只是将所有数据读入内存,然后对其进行处理,因此JVM将其视为大对象,并将其直接分配给旧版本,直到整个过程完成了,无法收集。