? ? ? ? 之前写百万以及千万的导出数据的时候,对于将数据写道csv文件并压缩这里没有什么大问题了,但是出现了其他问题为:
? ? ? ? 1、我们需要将数据从数据库中拿出来,并且在进行装配的时候出现了一些问题。
? ? ? ? 2、对于整体内存安全来说,如果直接将数据从数据库中拿出来百万级别以上的数据对于内存是非常不友好的。当问题出现比较大的时候会直接触发GC,造成瘫痪。
目前开发以及项目测试的是更多的使用mybatis来进行开发的,所以本文章讨论以及解决的的就是如何使用mybaits来解决流式查询并单条处理的问题。
使用MyBatis查询超大数据时,为了避免内存溢出(OOM, OutOfMemoryError)问题,可以采用以下几种解决方案:
流式查询 (Stream Result)
<select>
标签的resultType="void"
配合<resultMap>
和useResultHandler="true"
属性来实现流式查询。通过定义一个ResultHandler
接口的实现类,MyBatis会在遍历结果集的过程中逐行调用处理方法,这样每处理一行就释放一行的数据,从而避免一次性加载所有数据到内存中。<select id="streamingQuery" statementType="CALLABLE" resultType="void">
{your_query_here}
</select>
在Java代码中:
sqlSession.select("streamingQuery", parameter, new ResultHandler() {
@Override
public void handleResult(ResultContext context) {
Object object = context.getResultObject();
// 处理单行数据并确保及时释放资源
}
});
分页查询 (Pagination)
游标查询 (Cursor)
ResultSet
类型的返回值,结合Statement#setFetchSize()
方法可以实现类似游标的效果,有效地控制内存占用。优化SQL查询
分布式处理或批处理
数据库端缓存与分片策略
选择哪种方案取决于具体的应用场景、数据库类型以及系统架构设计。流式查询通常是在内存限制严格且必须一次性处理大量数据时的最佳实践。