100秒导出百万数据

背景

用户要求能够一次导出一个月的数据(10w量级别)

原理

在这里插入图片描述

需求分析

  • 生产环境担不起风险
  • 内存要平稳不能溢出
  • 对数据库缓存等中间件影响要小
  • 导出要尽可能快
  • 异步操作
  • 不能重复导出
  • 同时导出的操作不能超过10个
  • 必要的时候快速强制终止导出操作

代码展示

核心之一是主表的分页逻辑

每次从指定ID的位置读取符合条件的前1000条数据,取代传统的分页;必须用ID排序,让用户在excel自己调整排序;
(经测试每导出5w条数据,pageSize设置为1000或10000,导出时间没有区别,但是设置为100会慢2~3s)
在这里插入图片描述
select * from table where id > xx limit 1000,这种查询也有缺点,对于亿级别的数据而言,数据如果比较离散,第一次和最后一次会查询非常久,造成超时。所以可以优化为

select * from table where id > xx and id <(xx+100000) limit 1000

核心之二是每一批次的导出都先清空链表,方便内存回收,重复利用同一个链表,保证内存的稳定不溢出

这里用的阿里的easyExcel,这玩意写数据的时候会把整个excel文件一直放在内存;直到最后的finish(),71w数据的文件总大小为72M,平均每1W笔数据1M;可以考虑替换成XSSF(XSSF可以设置内存中的大小恒定为1M);
image.png

非核心之三利用in(索引值),取代偷懒的一条一条查库操作,减少网络传输次数,对导出时间能够提升一个数量级

image.png

非核心之四利用guava的本地缓存或者自己写个LRU解决一些需要远程查寻且重复度较高的数据,减少网络传输次数,避免用redis和内存溢出

非核心之五,对于总数不多(1000以内)但是需要用到的表数据,一次加载在内存,或者考虑分页预热到缓存

image.png

异步友好提示
image.png

利用redis的set解决导出前校验
image.png

重写toString(), 解决重复查询问题
在这里插入图片描述

如何更快,导出更多

  • 更快:多线程+多sheet;比如两个线程,A线程处理0-50W的数据
    B线程处理了50W-100W的数据,分别写到两个sheet
  • 更多:利用数仓
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值