栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Springboot+Mysql流式查询——避免内存溢出(OOM)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Springboot+Mysql流式查询——避免内存溢出(OOM)

话说笔者最近在做一个数据迁移的功能,说白了就是数据导出导入嘛。寻思着这还不简单,没想到第一步就GG了。

具体就是在数据库查询返回数据集时,由于数据集过大(大约几十万条吧)导致出现了内存溢出,即后台报错OOM。面对这种问题我们的第一反应肯定是将结果分页返回。但是分页却不得不考虑到几个问题:首先就是每页的大小,需要经过测试来确定一个合适的值,如果页面过大仍然可能出现内存溢出的问题;其次就是对于结果超大的数据集,在分页时偏移性能、查询开销和结果预加载似乎真的会损害分页方法的效率,简而言之就是会比较慢。

经过一翻查找,总算找到了比较适合的方法,即流式查询。这种查询是在java8进行支持的,所以首先需要我们的jdk在8以上。

先说使用效果吧,将50多万条数据查询并写入csv文件,以及下载,所需时间不足1分钟。

那么,它是如何实现的呢。很简单。

在使用 MySQL 时,为了真正流式传输结果,我们需要满足三个条件:
①设置结果集游标只能向前(Spring默认了)
②只读(设置@Transactional(readonly = true)即可)
③提取大小设置为 Integer.MIN_VALUE(解释一下,这代表逐行读取)

具体步骤使用如下:
第一步,先在repository中写sql查询数据,返回类型为Stream

    @QueryHints(value = @QueryHint(name = HINT_FETCH_SIZE, value = "" + Integer.MIN_VALUE))
    @Query(value = "select t from device t")
    Stream streamAll();

第二步:service方法中加入@Transactional(readonly = true),并调用第一步查询方法

    @Autowired
    private EntityManager entityManager;

    @GetMapping(value = "/csv")
    @Transactional(readonly = true)
    public void exportTodosCSV(HttpServletResponse response) {
        response.addHeader("Content-Type", "application/csv");
        response.addHeader("Content-Disposition", "attachment; filename=todos.csv");
        response.setCharacterEncoding("UTF-8");
          try(Stream todoStream = deviceRepository.streamAll()) {
           PrintWriter out = response.getWriter();
           todoStream.forEach((Device device) -> {
                String deviceString = JSON.toJSONString(device);
                out.write(deviceString);
                out.write("n");
                entityManager.detach(device);
            });
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

第三步 :上述代码中的entityManager.detach(device) 负责删除缓存的对象,只有这样才能保证内存即用即销。另外EntityManager 需要注入。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/644791.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号