JDBC的fetchsize和maxrows

本文介绍如何通过调整Java Statement的参数来优化大型SQL查询,防止内存溢出问题。主要探讨setMaxRows、setFetchSize及setFetchDirection三个方法的作用与使用场景。

在我们的项目开发中,可能有把SQL查询的结果保存到CSV然后提供下载的功能。当查询的结果集相当大的时候,很容易报内存不足错误(outofmemory)。那该怎么解决这种情况的内存不足错误呢?

    其实在JAVA的Statement中提供的方法可以解决这个问题。

   setMaxRows (int max) : 将此 Statement 对象生成的所有 ResultSet 对象可以包含的最大行数限制设置为给定数。

   setFetchSize (int rows) :为 JDBC 驱动程序提供一个提示,它提示此 Statement 生成的 ResultSet对象需要更多行时应该从数据库获取的行数。

    setFetchDirection (int direction) :向驱动程序提供关于方向的提示,在使用此 Statement 对象创建的 ResultSet 对象中将按该方向处理行。可以设置的参数是ResultSet.FETCH_FORWARDResultSet.FETCH_REVERSE 和 ResultSet.FETCH_UNKNOWN。

    setMaxRows方法的话是取得最大行,最大以后的数据会被丢掉。设置这个参数虽然可以避免报内存错误,不过在很多场合没法使用,因为查询的结果肯定想完整的抽取出来的情况很多。这个方法和limit类似。

    setFetchSize方法的话是JDBC查询和从结果集里面每次取设置行数,循环去取,直到取完。这个方法很常用的方法。默认是size是0.也就是默认是一次性把结果集的数据全部取出来,这样就容易造成内存不足。这个方法好像在自动提交模式下无效,需设置autocommit为false。

    setFetchDirection方法是设置从结果集中取数据的方向,有时候我们想从最后面往前取数据,用这个方法很方便,虽然sort可以实现同样的功能,但这个方法比order by sort更有效率。

### JDBC `fetchSize` 的使用说明及最佳实践 #### 设置合理的 `fetchSize` 当执行查询操作时,设置合适的 `fetchSize` 可以显著提高性能。默认情况下,驱动程序可能会一次性加载大量数据到内存中,这可能导致内存溢出或降低应用程序响应速度。通过调整 `fetchSize` 参数可以控制每次从数据库获取的数据量。 ```java Statement stmt = connection.createStatement(); stmt.setFetchSize(100); // 建议根据实际情况设定此值 ResultSet rs = stmt.executeQuery("SELECT * FROM large_table"); ``` #### 预编译语句中的 `fetchSize` 对于频繁使用的 SQL 查询,应该采用预编译的方式,并同样配置好 `fetchSize` 来优化读取效率[^1]: ```java PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setFetchSize(50); // 执行查询... ``` #### 结合流式处理大数据集 如果面对非常庞大的结果集,则应考虑配合使用游标的滚动特性以及较小的 `fetchSize` 实现逐条记录处理,从而减少对内存的压力并提升整体吞吐率。 ```java try (Statement statement = connection.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY)) { statement.setFetchSize(Integer.MIN_VALUE); try (ResultSet resultSet = statement.executeQuery(queryString)) { while (resultSet.next()) { processRow(resultSet); } } } ``` #### 关闭资源的重要性 无论何时都应当确保及时释放不再需要的对象实例,尤其是那些持有外部连接或其他昂贵资源者。即使设置了恰当大小的 `fetchSize` ,也务必记得关闭所有的 Statement Connection 对象来防止潜在泄漏风险。 ```java finally { if (rs != null && !rs.isClosed()) rs.close(); if (psmt != null && !psmt.isClosed()) psmt.close(); if (conn != null && !conn.isClosed()) conn.close(); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值