1 背景
当导出数据量很大时,分页查询会影响内存和数据库连接池,并且速度随着分页 offset 变大而变慢,因此需要优化
2 三种方法对比
主要参考:
1: https://ifrenzyc.github.io/2017/11/16/mysql-streaming/
2: http://knes1.github.io/blog/2015/2015-10-19-streaming-mysql-results-using-java8-streams-and-spring-data.html
测试 jvm 配置: -Xms512m -Xmx512m
测试数据量:60W 无查询条件
2.1 原生分页写法
1 | select * from table limit pageNo, pageSize |
内存:
时间耗时:三次测试导出,基本在200s~210s之间
2.2 优化之后的游标导出
注意:因为使用的主键索引查询范围,因为不支持排序,但是可以导出后让运营在 Excel 中手动排序
1 | # 每次查询后,将最大的 id 传入下次作为条件 |
时间耗时:三次测试导出,基本在15s左右
2.3 使用 stream
这是 mysql 本身支持的特性,使用流式处理数据
jpa 语法:1
2
3
4
5
6
Stream<Dao> streamAll();
streamAll.forEach(
// 业务处理
);
时间耗时:三次测试导出,基本在13s左右
3 最终选择
选择第二种,因为 stream 的缺点在于长事务,虽然是只读,不会有锁但是属于长连接,而且该 SQL 属于慢查询,在 DBA 就过不去。
而第二种更加容易接受和理解,虽然苦了运营~