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


            最近在做一个需求是导出较大的excel,本文是记录我在做需求过程中遇到的几个问题和解题方法,给大家分享一下,一来可以帮助同样遇到问题的朋友,二呢,各位大神也许有更好的方法可以指点小弟一下,让我顺便学习一下。
    背景::工头:“小钟啊,xx界面加个导出excel功能03以后的格式,需要能支持到excel的最大行,同时需要5个并发就行”
    我:“收到,但是数据大的时候速度可能比较慢。”
    工头:“你先做后续客户反馈了在给他加进度条。”
    Npoi神器介绍:SXSSFWorkbook 专门用来导出大数据用,他会把数据先写入C盘的临时目录;不会所有 都留在内存里;更详细介绍请百度或者参考(http://poi.apache.org/components/spreadsheet/how-to.html#sxssf
    有了这层基础开始劈里啪啦一段操作写代码;(以下代码非生产代码只是我为了帖子写重现问题的测试代码)
    首先开个线程模拟并发
    编写导出方法:记录时间、创建SXSSFWorkbook 代码如图:
    启动运行;
    好!第一口锅已造好,看这个提示,前面说了SXSSFWorkbook 是会先把缓存数据写入Windows临时文件里头的,这个目录正好是Windows的临时文件夹虽然是个错误但是验证了刚刚的说法;至于这个错误看提示 我们有个大胆的想法是文件占用问题,应该是创建文件的时候文件已经存在了,这样我们把npoi的dll打开来看看,通过看源码和各种f12我们看到了这么一段代码
    这里看到用来随机数,而我们知道net的随机数在极短的时间内生成是不可靠的(详见百度或者:
     
    早在年初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本身的缓存文件!
     
     
    最后导出完毕
    用时:
     
  • 相关阅读:
    Android开发环境搭建
    Noi 2016
    [二分图&最小割]
    [BZOJ 3145][Feyat cup 1.5]Str 解题报告
    [动态图]
    [组合数取模][中国剩余定理]
    [BZOJ 4436][Cerc2015]Kernel Knights
    [NOI 2014]做题记录
    [线段树合并]
    [树套树模板]
  • 原文地址:https://www.cnblogs.com/qqljcn/p/11917768.html
Copyright © 2020-2023  润新知