之前写文件方式:无论是走mybatis里面的方式还是从存过方式取数据,都是全部取出来之后放到先放到List里面,存过方式的还要放到map中,之后写文件的时候,一直写完为止。不在中间进行flush处理,代码如内部电脑所示。修改后代码如修改后的代码所示:三种方式。
修改点:将读文件的方式修改为返回resultSet方式或者分批读数据,之后分批调用写文件构件写文件,并且在每200条的时候刷新一下,指导总思路模型:https://my.oschina.net/u/859433/blog/790833
具体操作如下:
- 1、优化取数据
- 执行mybati方式取数据的将之前的所有handler里面的方法和逻辑移植到从库里面取数据的公共方法中,每次返回10000条数据,直到100000条,存储过程方式取数据的方式采取返回resultSet的方式,返回数据;具体代码如类
- 其中 mybatis里面方式的开始也可以采取返回resultSet方式的,具体操作如链接:
mybatis流式查询: https://www.jianshu.com/p/0339c6fe8b61
- 具体实现是下面这篇博文:
MyBatis Stream方式读取SELECT超大结果集:
- 如果需要改造为map或者其他类型的接收数据库参数的方法是:https://www.cnblogs.com/LiuPan2016/p/8391753.html
但是在修改的时候需要升级为mybatis的3.4.0以上的版本,升级后需要加拦截器才能使用(可以实现)
但是现在的mybatis的其他调用数据库方法封装的在工行内部的ctp工程里面,mybatis需要添加拦截器,现在的技术能力不足以排查所有封装的insert、selectOne等具体实现,有技术风险,故没有采用;
- 为什么要加拦截器:
https://www.jianshu.com/p/ec40a82cae28(Mybatis之工作原理)
和https://blog.csdn.net/u014297148/article/details/78696096(具体拦截器工作位置)
- 加哪个拦截器:https://www.cnblogs.com/EasonJim/p/7056700.html
- 怎样加:http://www.mybatis.org/mybatis-3/zh/configuration.html和https://www.nowfox.com/article/5298和https://blog.csdn.net/freyaalisa/article/details/78596992
- 2、内存分析
java内存溢出,一般会有以下几个位置,堆、栈、方法区、直接内存。
在现在的工程中jdk使用1.6的情况下,java虚拟类型HostPot版本在永久代中实现方法区
- java内存模型:https://blog.csdn.net/javazejian/article/details/72772461(第一张图)
- 在linux上java内存如何分配:http://www.importnew.com/14486.html(查看在物理机器上的最大限额)
- 上文中的Java虚拟机-----方法区和运行时常量池:
https://blog.csdn.net/sunshine__me/article/details/49992909
https://www.cnblogs.com/redcreen/archive/2011/05/04/2036387.html
和https://www.cnblogs.com/junwangzhe/p/6282550.html
- 升级为jdk1.8之后java内存的变化:https://www.zhihu.com/question/49044988和https://www.cnblogs.com/paddix/p/5309550.html
- java程序上面看jvm参数的方法:https://blog.csdn.net/nieyinyin/article/details/7162009(查看最大可利用的堆内存)
- java代码和java内存之间的关系如下:https://blog.csdn.net/shimiso/article/details/8595564(提一下就行)
- 触发gc的条件:https://blog.csdn.net/yhyr_ycy/article/details/52566105和https://www.zhihu.com/question/41922036( Minor GC ,Full GC 触发条件)参数:
- 提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。
- java堆中类和栈之间怎样引用:https://blog.csdn.net/wenbingoon/article/details/9102903
-
基于以上基础内容,现在就常见内存优化讲下:
- 3、jvm排查点和优化点:
- 选取jvm模式:https://www.cnblogs.com/haitaofeiyang/p/8336867.html和http://ryxxlong.iteye.com/blog/1696537(在开发工具中如何配置)和http://developer.51cto.com/art/201009/228035.htm(性能提升实验和硬件参数要求)
- OOM异常分类:https://blog.csdn.net/yuchao1076244056/article/details/51026551和https://www.jb51.net/article/110743.htm
-
- 基于以上内容,现在就现在项目中的内存优化讲下:
- 改造前将数据拿出来后,放到ArrayList里面,之后再放到Map里面,ArrayList和Map的扩容机制是:http://www.cnblogs.com/skywang12345/p/3308900.html (4 容量增加方式不同)
hashMap:https://blog.csdn.net/u013309870/article/details/70456355和https://www.cnblogs.com/chenssy/p/3521565.html和
https://www.cnblogs.com/yanzige/p/8392142.html(只看着一个,一、什么时候扩容)
可能导致拿的数据量导致ArrayList扩容明显,Map扩容占用内存不明显,设置ArrayList为10w时,显示一直占用内存很大,不适用,见自己电脑上的图,
- io流选取
将Priwrite改为Buffered,防止java内存里面的数据没有刷新到内存中,见jdk源码,Priwrite一直在循环调用自己的Flush,没有刷新到内存里面的操作,Buffered有,
也可以选择jdk在1.4以上加的nio技术里面的,可以加快写文件操作,写的快之后,可以更快的释放从数据库里面读取的存放到List的数据,释放内存,具体操作如下:http://langgufu.iteye.com/blog/2107023,(其中涉及的内存映射实现在下文中要重点介绍下)
上文中的内存映射:https://www.cnblogs.com/feng9exe/p/6889334.html,原文:http://kdf5000.com/2017/02/17/mmap内存映射/
看不懂的话可以粗略的看下这篇文章:https://blog.csdn.net/whoamiyang/article/details/53365385(解释上文中红色部分的内存映射)
上文中涉及的虚拟内存中涉及的计算机RAM和ROM:http://www.xitongzhijia.net/xtjc/20170623/100930.html
上文中的 Zero-Copy&sendfile浅析:https://blog.csdn.net/jiangbo_hit/article/details/6146502
选取内存映射的好处和其适用条件:https://blog.csdn.net/napolunyishi/article/details/18214929