open/docs/LARGEREAD.md
lqs cefdc4a027
Some checks are pending
Java CI / Test JDK ${{ matrix.java }} (adopt, 11) (push) Waiting to run
Java CI / Test JDK ${{ matrix.java }} (adopt, 17) (push) Waiting to run
Java CI / Test JDK ${{ matrix.java }} (adopt, 21) (push) Waiting to run
Java CI / Test JDK ${{ matrix.java }} (adopt, 8) (push) Waiting to run
Mirror the Github organization repos to Gitee / repo-sync (push) Waiting to run
ecxel数据高并发处理
2025-01-18 10:46:10 +00:00

3.5 KiB
Raw Permalink Blame History

10M以上文件读取说明

03版没有办法处理相对内存占用大很多。excel 07版本有个共享字符串共享字符串的概念这个会非常占用内存如果全部读取到内存的话大概是excel文件的大小的3-10倍所以easyexcel用存储文件的然后再反序列化去读取的策略来节约内存。当然需要通过文件反序列化以后效率会降低大概降低30-50%不一定也看命中率可能会超过100%

如果对读取效率感觉还能接受就用默认的永久占用单个excel读取整个过程一般不会超过50M(大概率就30M)剩下临时的GC会很快回收

默认大文件处理

默认大文件处理会自动判断共享字符串5M以下会使用内存存储大概占用15-50M的内存,超过5M则使用文件存储然后文件存储也要设置多内存M用来存放临时的共享字符串默认20M。除了共享字符串占用内存外其他占用较少所以可以预估10M所以默认大概30M就能读取一个超级大的文件。

根据实际需求配置内存

想自定义设置首先要确定你大概愿意花多少内存来读取一个超级大的excel,比如希望读取excel最多占用100M内存是读取过程中永久占用新生代马上回收的不算那就设置使用文件来存储共享字符串的大小判断为20M(小于20M存内存大于存临时文件)然后设置文件存储时临时共享字符串占用内存大小90M差不多

如果最大文件条数也就十几二十万然后excel也就是十几二十M而且不会有很高的并发并且内存也较大

 // 强制使用内存存储这样大概一个20M的excel使用150M很多临时对象所以100M会一直GC的内存
// 这样效率会比上面的复杂的策略高很多
   // 这里再说明下 就是加了个readCache(new MapCache()) 参数而已其他的参照其他demo写 这里没有写全 
  EasyExcel.read().readCache(new MapCache());

对并发要求较高,而且都是经常有超级大文件

 // 第一个参数的意思是 多少M共享字符串以后 采用文件存储 单位MB 默认5M
// 第二个参数 文件存储时内存存放多少M缓存数据 默认20M
// 比如 你希望用100M内存(这里说的是解析过程中的永久占用,临时对象不算)来解析excel前面算过了 大概是 20M+90M 所以设置参数为:20 和 90 
   // 这里再说明下 就是加了个readCacheSelector(new SimpleReadCacheSelector(5, 20))参数而已其他的参照其他demo写 这里没有写全 
EasyExcel.read().readCacheSelector(new SimpleReadCacheSelector(5, 20));

关于maxCacheActivateSize 也就是前面第二个参数的详细说明

easyexcel在使用文件存储的时候会把共享字符串拆分成1000条一批然后放到文件存储。然后excel来读取共享字符串大概率是按照顺序的所以默认20M的1000条的数据放在内存命中后直接返回没命中去读文件。所以不能设置太小太小了很难命中一直去读取文件太大了的话会占用过多的内存。

如何判断 maxCacheActivateSize是否需要调整

开启debug日志会输出Already put :4000000 最后一次输出大概可以得出值为400W,然后看Cache misses count:4001得到值为4K400W/4K=1000 这代表已经maxCacheActivateSize 已经非常合理了。如果小于500 问题就非常大了500到1000 应该都还行。