`
antival
  • 浏览: 5552 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

大量JDBC批处理内存溢出问题分析

阅读更多

2012年1月9日,去客户现场解决性能问题。

 

背景:客户需要数据从一个数据库到另一个数据库转移。本来可以使用ETL工具解决,但是由于一些客观原因又不能使用ETL系统,因此项目组自己做了一个数据迁移功能。除了业务部分的数据组织外,其他功能非常简单,就是利用JDBC组织数据,然后批量提交。

 

问题:数据量在19万条,内存控制在1G左右,在8万条左右,内存溢出。监控JVM,发现Old区域和eden区域都满了,GC很吃力,效果不好。因此定位内存泄漏。

 

代码分析:

原有代码使用hibernate分页获取数据,每次5000条,然后进入子程序,创建PreparedStatement,批量组织sql,提交,之后释放PreparedStatement和connection。规范都可以,最后释放也在finally块中。

 

第一步怀疑,hibernate的级联查询有问题,关闭jdbc部分,只查询。JVM监控没有问题,19万很快结束。

 

第二步怀疑,其他部分影响,通过堆dump分析,发现DB2的JDBC驱动类比较多。

 

第三步分析jvm监控,发现系统分页每次5000条执行结束后,内存跳一大块,五六次就把内存占满,因此基本确定是JDBC部分的问题。

 

第四步,增加了PreparedStatement批量操作的清理功能,比如pstat.clearBatch();,发现用处不大,依然问题依旧。

 

第五步,分析发现19万分每次5000笔也是38次,38次connnection和PreparedStatement可能有问题。因此修改代码,将链接和PreparedStatement都提出来,在循环之外。然后每次批量执行完毕都执行清理操作(pstat.clearBatch())。内存稳定,没有增加,问题解决。

 

结论:PreparedStatement批量执行方式占用内存有可能非常大(跟批量数据量有关系),如果只是使用close,包括connection的close,并不能及时释放,哪怕是强制gc也不能释放。

          解决的方法就是使用统一个PreparedStatement,那么假设它占用50M的空间,循环使用的情况下,只是覆盖没有新new一些地址,可能就是解决问题的思路。

 

不过上述结论没有经过全面测试和知识分析还存在一些疑问。

 

1,db2和oracle是否都这样?

2,怎么样才是PreparedStatement真正释放的方法,跟数据库连接池是否有关系。为什么我们原始代码不能及时gc掉呢?

3,数据迁移最佳模式是什么,我们做的是否是最佳的。我觉得只能是最简单的。

 

分享到:
评论

相关推荐

    JDBC批处理数据

    当处理大数据时,常见的问题是内存溢出和性能瓶颈。为了克服这些问题,可以采取以下几种策略: 1. **使用批处理:** 将多条SQL语句打包成一个批处理操作,一次提交给数据库。 2. **合理使用PreparedStatement:** ...

    关于hibernate的批处理

    10. **JDBC批处理API**: Hibernate底层使用JDBC的批处理API(Statement.addBatch()和Statement.executeBatch()),用户也可以直接使用JDBC批处理,绕过Hibernate的部分逻辑,获取更高的性能。 11. **性能优化注意...

    greenplum_jdbc_5.1.4.zip

    - 注意处理大结果集时的内存管理,避免一次性加载大量数据导致内存溢出。 - 使用JDBC的批处理功能提高批量操作的效率。 6. **常见问题及解决方案** - 连接超时:检查网络状况,或者调整数据库的连接超时设置。 ...

    jdbc批量插入大字段

    批量过大可能导致内存溢出,过小则可能无法充分利用批处理的优势。 - **事务管理**:将批量插入操作包裹在事务中,可以确保数据的一致性。如果在批量操作中发生错误,整个事务可以回滚,避免了部分插入的数据不...

    JDBC问题解决的方法

    - **大结果集**:对于大量数据,考虑使用批处理或存储过程,避免一次性加载所有数据导致内存溢出。 4. **错误处理** - **捕获SQLException**:使用try-catch块捕获并处理SQLException,获取具体的错误信息。 - *...

    jdbc驱动jar包

    ResultSet中的游标允许按需读取数据,避免一次性加载大量结果集导致内存溢出。批处理功能允许一次性发送多条SQL语句,提高执行效率。 10. 错误处理和关闭资源: 使用try-with-resources语句可以自动关闭数据库...

    效率很高的java jdbc类

    2. **迭代器模式**:提供一个迭代器接口,使得遍历结果集更加灵活且节省内存,避免一次性加载所有数据导致内存溢出。 3. **类型转换**:根据需要自动将数据库中的值转换为适当的Java类型,例如将字符串转换为日期、...

    JAVAWEB-17:JDBC编程进阶2

    - 使用ResultSet的滚动和定位功能,可以更高效地遍历大量数据,避免一次性加载全部记录导致内存溢出。 - ResultSet的关闭非常重要,及时关闭可以释放数据库资源,防止内存泄露。 5. **事务管理(Transaction ...

    处理大数据量excel

    1. **读取Excel**:使用Apache POI等库读取Excel文件,可以逐行或按需加载数据,避免一次性加载整个文件导致内存溢出。 2. **预处理数据**:在读取数据后,可能需要进行数据清洗、格式转换等预处理步骤,以符合...

    jdbc.rar_jdbc

    如果需要处理大量数据,应考虑使用迭代器或流,以避免内存溢出。 此外,JDBC还提供了事务管理功能,通过Connection对象的`setAutoCommit()`和`commit()`方法可以控制事务的提交和回滚。对于性能优化,可以使用...

    Hibernate批量处理

    - **内存管理**:合理规划内存使用,确保不会因为内存溢出而导致程序崩溃。 - **测试验证**:在生产环境中部署前,一定要充分测试批量处理逻辑,确保其稳定性和性能表现。 #### 五、总结 批量处理是提高Hibernate...

    sqljdbc.jar

    - 在处理大量数据时,要注意内存管理,避免因结果集过大导致的内存溢出问题。 - 考虑到性能优化,适当使用连接池来复用数据库连接。 总的来说,`sqljdbc.jar`是Java开发者与SQL Server数据库之间的重要桥梁,它为...

    Hibernate

    传统的Hibernate数据插入方式往往采用单次插入单个实体对象的方式,这在处理小规模数据时效率尚可,但在处理成千上万乃至百万级别的数据时,则显得力不从心,甚至可能导致内存溢出等问题。解决这一问题的关键在于...

    浅析Hibernate下数据批量处理方法.doc

    `batch_size`设置的是JDBC批处理的大小,即在提交事务前,Hibernate会积累多少条SQL语句。增大这个值可以减少与数据库的交互次数,从而提高性能。 在处理批量插入时,避免内存溢出的关键在于合理控制缓存。上述代码...

    JDBC - 结构优化1 学生信息系统源码

    4. **结果集管理**:正确处理ResultSet,尤其是在大数据量返回时,避免一次性加载所有数据导致内存溢出。使用迭代器或分页查询来控制数据的读取。 5. **事务管理**:对于涉及多条数据库操作的任务,如学生信息的...

    JDBC数据库连接操作

    4. **设置合适的批处理大小**:避免一次性处理太多数据导致内存溢出。 5. **配置连接池**:根据应用需求调整连接池大小,避免空闲连接过多或连接不足。 6. **处理异常**:捕获并适当地处理SQL异常,确保程序健壮性。...

    jdbc优化连接数据库

    - 使用`LIMIT`子句限制返回的数据量,避免一次性加载大量数据导致内存溢出。如果可能,使用游标(Cursor)逐行处理结果。 7. **使用连接池的健康检查和超时设置**: - 配置合适的连接超时和空闲时间,确保连接池...

    利用poi获取excel数据批量插入大量数据到mysql

    在IT行业中,处理大量数据是常见的任务之一,尤其是在数据分析、报表生成或数据迁移等领域。本教程将详述如何使用Apache POI库读取Excel数据,并通过Java的JDBC接口批量插入到MySQL数据库中。Apache POI是Java平台上...

    Hibernate下数据批量处理解决方案

    在上述例子中,当尝试向数据库插入100,000条数据时,由于默认情况下Hibernate会将所有持久化对象保留在一级缓存中,随着数据量的增加,内存消耗也会迅速增长,最终导致内存溢出。因此,我们需要对一级缓存进行管理。...

    三种JDBC批量插入编程方法的比较

    过大可能导致内存溢出,过小则可能无法充分利用批量操作的优势。 在`JDBCBatchInsertTest.java`中,你可能会看到对这些批量插入方法的性能测试,通过计时和比较来确定哪种方法更适合特定的场景。 总结来说,选择...

Global site tag (gtag.js) - Google Analytics