查看原文
其他

ef+Npoi导出百万行excel之踩坑记

点击上方 "程序员小乐"关注, 星标或置顶一起成长

每天凌晨00点00分, 第一时间与你相约

每日英文

No matter when you start, it is important that you do not stop after starting. No matter when you end, it is more important that you do not regret after ended.

不论你在什么时候开始,重要的是开始之后就不要轻言放弃;不论你在什么时候结束,重要的是结束之后就不要后悔。


每日掏心

人生的轨迹不一定会按你喜欢的方式运行。有些事你可以不喜欢,但不得不做;有些人你可以不喜欢,但不得不交往。


来自:小菜鸟 | 责编:乐乐

链接:cnblogs.com/qqljcn/p/11917768.html

程序员小乐(ID:study_tech)第 704 次推文   图片来自网络


往日回顾:我很神秘的采访了一位 Pornhub 工程师,聊了这些纯纯的话题



   正文   


最近在做一个需求是导出较大的excel,本文是记录我在做需求过程中遇到的几个问题和解题方法,给大家分享一下,一来可以帮助同样遇到问题的朋友,二呢,各位大神也许有更好的方法可以指点小弟一下,让我顺便学习一下。


背景::工头:“小钟啊,xx界面加个导出excel功能03以后的格式,需要能支持到excel的最大行,同时需要5个并发就行”

我:“收到,但是数据大的时候速度可能比较慢。”

工头:“你先做后续客户反馈了在给他加进度条。”

Npoi神器介绍:SXSSFWorkbook 专门用来导出大数据用,他会把数据先写入C盘的临时目录;不会所有 都留在内存里;更详细介绍请百度或者参考(poi.apache.org/components/spreadsheet/how-to.html#sxssf)

有了这层基础开始劈里啪啦一段操作写代码;(以下代码非生产代码只是我为了帖子写重现问题的测试代码)

首先开个线程模拟并发

编写导出方法:记录时间、创建SXSSFWorkbook 代码如图:

启动运行;

好!第一口锅已造好,看这个提示,前面说了SXSSFWorkbook 是会先把缓存数据写入Windows临时文件里头的,这个目录正好是Windows的临时文件夹虽然是个错误但是验证了刚刚的说法;至于这个错误看提示 我们有个大胆的想法是文件占用问题,应该是创建文件的时候文件已经存在了,这样我们把npoi的dll打开来看看,通过看源码和各种f12我们看到了这么一段代码

这里看到用来随机数,而我们知道net的随机数在极短的时间内生成是不可靠的(详见百度或者:

docs.microsoft.com/zh-cn/dotnet/api/system.random.-ctor?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev16.query%3FappId%3DDev16IDEF1%26l%3DZH-CN%26k%3Dk(System.Random.%2523ctor);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.0);k(DevLang-csharp)%26rd%3Dtrue&view=netframework-4.8)也就是说生成一样的文件名,然后我们在通过 github里可以看到

 

早在年初NPOI就对这个问题做了更改就换成guid了,随后我来到了nuget

nuget最新版 是去年12月份发布,并没有包含上面的更改;

所以呢 要么github下载最新版编译要么自己解决,想了想如果换版本的话以前的功能可能会影响到所以,我们就在外面加一把小锁吧!如图

 

这样呢我们在试试!

 

很好 不会在出现文件占用问题了;好继续导出!

既然是都先写入缓存文件是不是占用的内存就很小了 来看看

2G多。。。什么情况,还在涨

 

3G。。。这明显不符合工头的需求了,然后终于它炸了

第一念头是为啥我该怎么办,设置GC的回收模式?手动多GC?还是要把代码给拿下来看看,看看这么大内存哪里没释放文件?冷静、冷静、想想,既然是内存爆了 那么正确流程应该是抓取看看是什么吃的内存得出结果再去改东西,

发现了啥是不是很熟悉的东西?状态管理、包装类,想到了啥 EF的“模型跟踪”这个功能占用的内存最大了。那就去掉吧 加上这么一句 意思是无跟踪查询 ,修改实例后SaveChanges不对对它生效;

(AsNoTracking 更详情理解介绍请百度在加上msdn:https://docs.microsoft.com/zh-cn/ef/ef6/querying/no-tracking?redirectedfrom=MSDN )

现在在继续导出看看:

内存是吃的不大了,

可以看出临时文件还是很大的,这还没导完呢,所以做的时候 尽量要保证下硬盘的空间!

等待。。。

总结:

1.导出大数据用SXSSFWorkbook

2.构建SXSSFWorkbook 时候lock或者自己编译最新版本

3.我们做导出时,ef查询数据后记得加AsNoTracking 关闭绑定跟踪。(以后日常开发中如果只需要查询的也可以这样做)

4.SXSSFWorkbook 导出大数据 临时文件夹所在的硬盘不能太小 因为会生成大于excel本身的缓存文件!

 

 

最后导出完毕

用时:

 

欢迎在留言区留下你的观点,一起讨论提高。如果今天的文章让你有新的启发,学习能力的提升上有新的认识,欢迎转发分享给更多人。

欢迎各位读者加入程序员小乐技术群,在公众号后台回复“加群”或者“学习”即可。

猜你还想看


阿里、腾讯、百度、华为、京东最新面试题汇集

假如有人把支付宝存储服务器炸了(物理炸),大众在支付宝里的钱是不是就都没有了呢?

7 个显著提升编码效率的 IntelliJ IDEA 必备插件

Spring Boot 集成 Ehcache 缓存,三步搞定!


关注「程序员小乐」,收看更多精彩内容
嘿,你在看吗?
视频 小程序 ,轻点两下取消赞 在看 ,轻点两下取消在看

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存