zoukankan      html  css  js  c++  java
  • 关于Java导出100万行数据到Excel的优化方案

    1》场景

      项目中需要从数据库中导出100万行数据,以excel形式下载并且只要一张sheet(打开这么大文件有多慢另说,呵呵)。

      ps:xlsx最大容纳1048576行 ,csv最大容纳1048576行,xls最大容纳65536行,但是存放相同的数据量 文件大小排序:xls>csv>xlsx ;xls是biff8的二进制文件,就是个B+树而xlsx是 xml的zip压缩文件。

    2》常规做法

      按照平常的做法,先到数据库中取数然后循环组装成一个list,然后用excel工具(我用的是POI)生成excel。

    3》遇到的问题

      1' 内存经常溢出。

      2' 组装list,生成excel慢,50万的数据花了一个小时都没见完成。

    4》解决方法

      1' POI 改用 SXSSFWorkbook 参看 比如SXSSFWorkbook wb = new SXSSFWorkbook(100);在内存中只保留100行记录,超过100就将之前的存储到磁盘里,

          2' 调整JVM 相关的参数 -Xmx....

        3' 循环中减少使用new,尽量复用;String改为StringBuffer就不说了,重点是在组装一行数据时,一直比较喜欢用map来拼装,但是在我功能上发现还是耗内存的,后来的GC时间太长,造成严重拖累组装数据的效率,后来发现由HashMap改为用StringBuffer拼接行数据效率直接就上去了,当然指定合理的StringBuffer的起始容量效率就更好了。

      ps:StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。

          4' 下载任务由同步改为异步,用户提交了后只要等待邮件通知即可,我用了quartz。

    5》效果

        100万数据组装以及生成excel大概要10分钟,平均下来1分钟10万条,我的小黑腰不酸腿不疼了。

    好了就这些,我也看了,网上导出很多是分批导出或者用csv的解决的,但是我就这样的需求,人家任性没办法,我的方法还有待完善的地方,欢迎交流。

    本文原创,转载请注明出处,谢谢。

  • 相关阅读:
    Hibernate提供的内置标识符生成器
    ThreadLocal解析
    save()/saveOrUpdate()/merge()的区别
    Hibernate中主键生成策略
    session/SessionFactory线程非安全和线程安全
    load/get延迟加载和及时加载
    最长公共子序列:递归,非递归实现
    c语言,递归翻转一个单链表,c实现单链表
    最长递增子序列(Longest Increase Subsequence)
    求一串数字中——和最大的连续子序列; 求一串数字差值的绝对值最小的两个数字
  • 原文地址:https://www.cnblogs.com/hsuchan/p/4174433.html
Copyright © 2011-2022 走看看