SpringBoot 实现 MySQL 百万级数据量导出并避免 OOM 的解决方案

本文介绍了如何在SpringBoot应用中,利用MyBatis和MySQL的Stream查询来实现百万级数据的导出,以避免内存溢出(OOM)。关键点在于设置fetchSize为负值,实现数据逐条处理并写入CSV文件,减少内存占用。同时,文章提供了具体的MyBatis配置和代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考链接:https://blog.youkuaiyun.com/liliangpin/article/details/129870300
这篇文章只用于记录,等自己想实现了好找,大家感兴趣的可以看上面的原链接

如何实现百万级数据量导出

从技术上讲,为了避免OOM,我们一定要注意一个原则:

~ 不能将全量数据一次性加载到内存之中。

Mysql本身支持Stream查询,我们可以通过Stream流获取数据,然后将数据逐条刷入到文件中,每次刷入文件后再从内存中移除这条数据,从而避免OOM。

数据逐条刷入文件,数据量达到百万级,文件格式就不要采用excel了,excel2007最大才支持104万行的数据。这里推荐:
以csv代替excel…

MyBatis实现百万级数据导出

MyBatis实现逐条获取数据,必须要自定义ResultHandler,然后在mapper.xml文件中,对应的select语句中添加fetchSize=“-2147483648”。
xml文件内select语句内容

最后将自定义的ResultHandler传给SqlSession来执行查询,并将返回的结果进行处理。

MyBatis实现百万级数据导出的具体实例

以下是基于MyBatis Stream导出的完整的工程样例,我们将通过对比Stream文件导出和传统方式导出的内存占用率的差异,来验证Stream文件导出的有效性。

我们先定义一个工具类DownloadProcessor,它内部封装一个HttpServletResponse对象,用来将对象写入到csv。

public class DownloadProcessor {
   
    private final HttpServletResponse response;
     
    public DownloadProcessor(HttpServletResponse response) {
   
        this.response = response;
        String fileName = System.currentTimeMillis() + ".csv";
        this.response.addHeader("Content-Type", "application/csv");
        this.response.addHeader("Content-Disposition", "attachment; filename="+fileName);
        this.response.setCharacterEncoding("UTF-8");
    }
     
    public <E> void processData(E record) {
   
        try {
   
            response.getWriter().write(record.toString()); //如果是要写入csv,需要重写toString,属性通过","分割
            response.getWriter().write("\n");
        }catch (IOException e){
   
            e.printStackTrace();
        }
    }
}

然后通过实现org.apache.ibatis.session.ResultHandler,自定义我们的ResultHandler,它用于获取java对象,然后传递给上面的DownloadProcessor处理类进行写文件操作:

public class CustomResultHandler implements ResultHandler {
   
 
    private final DownloadProcessor downloadProcessor;
     
    public CustomResultHandler(
            DownloadProcessor downloadProcessor) {
   
        super();
        this.downloadProcessor = downloadProcessor;
    }
     
    @Override
    public void handleResult(ResultContext resultContext) {
   
        Authors authors = (Authors)resultCont
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值