Mysql中使用JDBC流式查询避免数据量过大导致OOM
一、前言
java 中MySQL JDBC 封装了流式查询操作,通过设置几个参数,就可以避免一次返回数据过大导致 OOM。
二、如何使用
2.1 之前查询
public void selectData(String sqlCmd) throws SQLException { validate(sqlCmd); Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = petadataSource.getConnection(); stmt = conn.prepareStatement(sqlCmd); rs = stmt.executeQuery(); try { while(rs.next()){ try { System.out.println("one:" + rs.getString(1) + "two:" + rs.getString(2) + "thrid:" + rs.getString(3)); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } finally { close(stmt, rs, conn); } }
2.2 现在流式查询
public void selectData(String sqlCmd,) throws SQLException { validate(sqlCmd); Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; try { conn = petadataSource.getConnection(); stmt = conn.prepareStatement(sqlCmd, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE); rs = stmt.executeQuery(); try { while(rs.next()){ try { System.out.println("one:" + rs.getString(1) + "two:" + rs.getString(2) + "thrid:" + rs.getString(3)); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } finally { close(stmt, rs, conn); } }
可知只是prepareStatement时候改变了参数,并且设置了PreparedStatement的fetchsize为Integer.MIN_VALUE。三、 结果对比对于同一个sqlCmd,同一批数据,使用两种方式占用内存对比如下:
-
非流式编程
-
流式编程
另外非流式方式由于是把符合条件的数据一下子全部加在到内存,并且由于数据量比较大,需要mysql处理的时间比较长,我测试情况下需要一分钟才会返回结果到内存(数据量比较大),然后才能通过数据集返回数据。
而流式方式是每次返回一个记录到内存,所以占用内存开销比较小,并且调用后会马上可以访问数据集的数据。
--------------
转自
链接:https://www.jianshu.com/p/c1e6eeb71c74