流式查询 easyExcel Mybatis

针对每月月初的财务月结需求,解决由于大量数据导致的内存溢出问题。通过使用Mybatis的流式查询减少内存占用,配合EasyExcel将数据分批写入硬盘,同时采用Redisson信号量限流控制并发,以及MQ解耦微服务,实现高效、稳定的报表生成。测试显示,流式查询比分页查询速度提升约4-5倍。
摘要由CSDN通过智能技术生成

流式查询

问题概述

OOM问题的案例,背景是【在物流领 域,针对各个下级⽹点⽽⾔,每⽉1⽇〜9⽇是⼀个进⾏财务⽉结的重要时间节点,在这个关键节点 上,各个⽹点会需要使⽤导出功能输出寄派件、费⽤客⼾信息等多种信息进⾏汇总结算】。也就是 说,在⽉初的时候,每个⽹点都要统计⼀个⽉的各种流⽔(寄件,收件等),最后以excel的表格 的形式下载给客⼾。在这个业务中为什么容易发⽣OOM呢,平均1个⽹点的1个⽉的流⽔⼤约在 30w⾏左右,根据计算得出⼤约500⾏数据会占⽤1M内存,1个站点把30万⾏⼀股脑读到内存中就 会占⽤600M内存,试想⼀下如果全国的⽹点都在⽉初集中下载报表的话,jvm是很容产⽣内存溢 出的问题的。

解决⽅案概述

这样⼀个棘⼿的问题⽤⼀个单⼀的解决⽅案是不够的,主要采取了以下的解 决⽅案

2.1 ⽤硬盘换内存

接到⼀个统计数据请求的时候,⼀次性把30w条数据从数据库中读到⼀个List的做法,显然是不 现实的,这样⼀个list将会占⽤600M内存。我们可以分⻚查询,每次查询1000条数据,然后往 硬盘上写,多读取⼏次,⼀点⼀点的把所有的数据都读出来,⼜⼀点⼀点的往硬盘上写,这样 在这个过程中,占⽤的内存就会少很多,主要变成了对硬盘的占⽤。这⾥写excel的技术,选择 的是阿⾥巴巴的easyexcel.

2.2 使⽤mybatis的流式查询

使⽤【流式查询】查询成功后返回的是⼀个迭代器⽽不是⼀个集合,应⽤每次都从迭代器中获 取⼀条查询结果,能够降低内存的使⽤。试想⼀下如果我们不使⽤流式查询,⼀次性从数据库 中取30万条数据,内存根本不够⽤,这时我们只能选择分⻚查询了,⽽分⻚查询的性能取决于 表设计以及索引的设计,⼤量数据分⻚查询的性能是很低的,耀哥对⽐使⽤流式查询和分⻚查 询两种⽅案,得到的结论是取30万条数据,流式查询的速度⼤约是分⻚查询的4,5倍左右

2.3 使⽤redission 的信号量限流

⽣成⼀个⽉的流⽔报表是⼀个⾮常耗时的操作,⽤⼾也不可能⻢上就要结果,所以学⽣的公司 对同时⽣成报表的请求做了限制,同时只处理10个报表的⽣成,这个期间再有⽣成报表的请 求,我们将会让这些请求排队,等到前⾯的报表⽣成完毕后,再处理后⾯的请求。报表⽣成成
功后,再通知客⼾主动去下载,这⾥使⽤redisson分布式锁的信号量来限制同时创建报表的线 程数量。

2.4 mq解耦,微服务拆分

本次业务中,读数据库,写excel⽂件,上传到⽂件服务器这三个操作都⾮常耗时,学⽣的公司使 ⽤mq解耦,把这次请求拆分成3个微服务,这样读,写,上传就不会相互影响。

流式查询解决方案

数据库插入十万条数据
public class easyTest {
   
    int a=0;
    @org.junit.Test
    public void add(){
   
        while (a<=100000){
   
            TbGoodMapper mapper = MySqlSessionFactory.getSession().getMapper(TbGoodMapper.class);
            TbGood 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值