笔者在开发中处理MySql大结果集时碰到一个问题,单表数据有2000w,而且数据是每天递增的,需要每天凌晨2点用定时任务导出到ftp。
方式一:查出所有数据到内存处理(不可行)
直接使用SELECT * FROM TABLE....
查出所有的数据到内存,然后再处理。由于数据量太大了,直接就报java.lang.OutOfMemoryError
。
方式二:使用limit 分页查询(不可行)
由于方式一对于大结果集肯定是不可行、于是我一开始就使用limit
分页的方式进行查询,一次性读取部分数据然后处理。虽然不会出现OOM的错误,但是这种查询方式效率极其低下。
方式三:使用流式读取
//以JdbcTemplate方式为例,其他方式也是相同设置setFetchSise(int arg)即可。
JdbcTemplate jdbcTemplate = new JdbcTemplate();
StringBuilder sb = new StringBuilder("SELECT * FROM TABLE...");
jdbcTemplate.query(sb.toString(), preparedStatement -> {
//设置流式读取的大小
preparedStatement.setFetchSize(Integer.MIN_VALUE);
}, rs -> {
while (rs.next()) {
//do somethings ......
}
return null;
});
流式读取的原理是:每次从MySql服务端读取一定数量的数据到内存,然后再处理,所以避免了OOM.