POI导出大数据量解决方案

导出报表导不出 一个月:

分析问题:

1、开始认为报表查询sql不够优化,sql优化多次之后 发现在生产数据库,sql根本就查询不出结果集;

2、如果sql或存储过程查询很慢会造成数据库连接超时;

3、POI HSSFWorkbook、XSSFWorkbook生成excel 文档会造成JVM内存溢出;

4、如果数据库返回结果集太多,也会造成内存溢出

5、http请求超时

6、java cpu占用率过高

解决方案:

¢问题一:sql根本就查询不出结果集

¢采用存储过程,分布创建临时表。

¢问题二:数据库连接超时

¢增加数据源配置

<property name="maximumActiveTime" value="2400000"></property>

该属性描述:表示连接的最大活动时间,即这个连接在指定的时间内没有完成任务(如查询),将 org.logicalcobwebs.proxool.HouseKeeper 是一个后台线程 用于监控线程池的。

1、用于检查线程池中的每个连接是否超过了最大获得时间 2、如果超过了,会调用connectionPool.removeProxyConnection 回收连接

¢问题三:POI HSSFWorkbook、XSSFWorkbook生成excel文档会造成JVM内存溢出

¢查询POI官网,了解POI导出大数据提供的最优生成excel解决方案如下:

¢问题四:数据库返回结果集太多也会造成内存溢出

¢通过调用存储过程返回结果集数量,采用分页方式导出报表,以zip文件给用户提供下载

¢问题五:http请求超时

¢由于导出报表时,数据量较大,导致http请求超时,采用导出报表方式线程执行生成excel文件,生成文件之后以邮件方式发送提醒给用户

¢问题六:java cpu占用率过高

¢各位请珍重,尽量少用java反射(大数据mybatis少用封装类),反射会造成CPU占用率过高,据网上透露通过java反射调用方法与普通方法调用性能相差数百倍。具体原因请各位参考源码,其中mybatis返回结果集先默认为HashMap,设置为封装类时需要通过java反射转化为封装类

CPU

Java CPU占用率高解决方案之一

解决思路:

Java程序很多时候是多线程运行的,但是单个线程只能运行一个CPU.解决某个cpu占用率高的整体思想如下.找到具体线程对应的程序,然后具体解决. 本文档讲一种特殊占用cpu高就是大名鼎鼎的java GC.

解决流程图如下:

现在进入怎么定位cpu是哪个线程产生的。

1.首先用top命令监控cpu运行情况,如下图。

2.找到cpu占用率高的pid.

使用

Top -p pid 监控单个pid的情况。

3.Ctrl+H 打开线程执行情况( linux 使用子进程实现线程)

4.当 cpu 冲高的时候 使用jstack 将线程信息打印到文档中

打印出来的文档如下 :

5.将cpu占用率高的线程 转化为16进制,然后再stack.log找出相应的信息。

通过上面的步骤我们就可以找到cpu是由那个具体的线程产生的。

下面介绍如果是GC 产生的情况下处理:

使用visualvm 定位 如下图:

可以查看到哪个最大,以及最大的是由哪种类或者方法产生的!

下面介绍怎么确定gc的运行的具体信息。

可以配置GC log

-Xloggc:$CATALINA_BASE/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps.

如:

可以看出是Full Gc 太频繁,要减少Full GC.

注意:不建议调整gc内存的分配比例,因为那个是折中的,最通用,如果修改后,可能是针对莫个业务好,但是会影响其他的执行性能,所以尽量从代码上优化,减少对象进入老生带。

.

下面介绍 一下JMap使用,因为发生内存不够或者gc 导致的CPU很高都是和对象相关。

例如下面场景,

1 .Jmap .

我把10万个对象插入list想看是否真的在内存,或者有多少个,可以用:

对应的内码:

还有在生产上我猜想CPU很高或者内存不够是因为Map导致 可以用JMap 去追踪:

经验分享 程序员 微信小程序 职场和发展