SQLite优化记录 + 资源及时释放以免OOM -- 又被Java忽悠一次

       今天很恼火, 大致状况是这样的, 程序直接进入数据库写操作InsertDBActivity中,异步完成80W条数据的插入, 不会OOM; 当我在进入InsertDBActivity之前先来了个用户介绍页(滑动预览6张图片), 然后换了个高清的背景图,够炫,但是悲剧的一幕发生了   在log中可以明显的看到 数据插入到40W多的时候 OOM了! 什么原因呢? 我debug追踪了好久,代码没怎么改动呀,,任何地方都断点看了, 就是老是出现内存溢出, 我就纳闷了·······  只有一种情况, 我加的这些代码中有问题! 可是我也没加什么东西呀?   不对··  有6张介绍页!

      不会吧? 6张介绍页加起来内存才占了不到1M,, 这个引起的oom?  与测试机MI2的内存比起来显然微不足道, 但是没有其他地方动过啊! 哦  还有一张高清的背景图·· 但是我看了下工程背景文件大小, 也不到1M,, 怒了··········

       遂········

      1.将介绍页屏蔽掉, 

      2.将高清背景图去掉,

      3.将数据量保持在80W . 

      再走一遍  果然, 没事嘞~~    但是······

      还原1,2,   将数据量再提升至80W, 内存溢出;

      还原1,2,   将数据量降至20W, 不溢出;

      还原1,2,   将数据量提升至40W, 内存溢出······   我去   有完没完啊

     然后就乖乖的检查代码执行流程, 查找一切可以导致内存溢出的可能···············

     跟踪到activity的跳转一行, 我怎么看都像少了点什么, 但又说不上来, activity不是压栈管理嘛, 也就没网这上面想, 大爷的, 问题就出在这里············

     当activity入栈处于非栈顶,activity中的资源未消失,等待出山,只有等到内存资源不够用的时候系统才会自动清理; 然后就联想到Java不是有垃圾回收机制来着, 然后就理所当然的认为没问题, 再说, MI2的内存那么大, 这点资源占的内存微乎其微, 然后就理所当然的在排查着错········

int dataIsLoaded = sp.getIntValue(ConstancessUtil.DATA_LOADED);
			if(username.equals("1")) {//跳转至中层领导界面
//				new LoginAsyncTask(KPILoginActivity.this).execute(username, password, String.valueOf(dataIsLoaded));
				if(dataIsLoaded == 1) {
					startActivity(new Intent(this, MainLSPKPIActivity.class));
					finish();
				} else if(dataIsLoaded == 0) {
					startActivity(new Intent(this, TestDBActivity.class));
					finish();
				}
			} else if(username.equals("2")) {//跳转至高层领导界面
//				new LoginAsyncTask(KPILoginActivity.this).execute(username, password, String.valueOf(dataIsLoaded));
				if(dataIsLoaded == 1) {
					startActivity(new Intent(this, SeniorLeaderMainActivity.class));
					finish();
				} else if(dataIsLoaded == 0) {
					startActivity(new Intent(this, TestDBActivity.class));
					finish();
				}
			}

       当我看见跳转之后没有 finish(); 的时候我就想了, 是不是就这点资源泄漏, 未及时清理的原因, 遂手动加上了销毁finish(); ; 经过测试, 可以了; 

      大哥不是吧, 这也行??

                      手机内存 & 运行时内存     什么关系?  有待深究··

       我回头想了想, 导致自己思维混乱的几点:

       1. 书写太随意, 很多问题当想到点上的时候硬是想当然的认为不可能, 没有经过实践的检验;

       2.太教条, 将Java许下的美好诺言信以为真-- 垃圾自动回收--  

       3.要大胆尝试, 大胆质疑, 哪怕是自己写的自认为很得意的代码, 也要有推翻重来的勇气!

    其实回头看,  就是用finish()方法将前一个activity销毁, 其资源也被释放, 不占据手机的运行内存; 如果没有finish()方法, activity中的所有资源在栈中,资源未释放,依然占据着内存, 可能一般情况下不会出现内存泄露,毕竟现在的手持设备的硬件配置都挺高,  但是当数据量刚刚好的时候··········它就偏偏发生了, 而且除了这几张图片, 别无他因; 所以不要凭借着现在硬件的优势而丧失了我们编码的优秀原则, 移动端不是PC端,本身就是一种限制!

      另···附SQLite亲测参数以供参考(不同设备可能有所差异):

      测试机器:    MI2 
      数据表字段:18个全满

      插值--

             -------记录数------------插值耗时-------------生成db文件大小  --------普通查询耗时 -------优化查询耗时-----

                     535680条           (193-238)s              38.51M                             8S扫描一次              2S内

                     803520条           443s左右                 57.54M                             10s+ ANR                3S内

                     807557条           临界溢出值              ********                                     **                          **

                     100W                  outofmemory          ********                                     **                           **

    其实数据量小的时候, 怎么查询都可以; 但是数据量一旦突破几十万, 甚至过百万, 就需要优化了; 

    如果不优化查询, 时间很长, 不太好, 但是如果优化的话, 查询逻辑都要重新推翻重新设计; 有时候真的很无奈 , 真的。

    这个项目的设计,本身有存在些不妥, 但是没有办法, 客户需求; 但是手机毕竟是个手机, 内存有限, 处理能力也相当**, 用手机来存储百万级的数据是不是有点****

    我到现在查询优化的还不够快, 还能更快! 这是要将手机的cpu烧了的节奏吗?   还有, 目标数据源是100W-300W之间, 我的个天呐, 现在80多w的时候就OOM了, 怎么整!!!!!!

      本身表设计的时候存在着父子节点查询, 即树的概念;

     优化逻辑过程: 

               原逻辑:    用 select * from region where uid like  ‘parentID%’  即可以通过当前的ReginID查出其所有子节点;然后经过id位数来进行筛选操作;

                                   数据量小的时候这种查询不要太方便, 不要太爽; 但是数据量大的时候, 要加索引进行优化查询, 很不幸, like函数与索引不兼容---即like()无效······

                                   怎么办!!!!!!!!!!!!!!!!!!!!!!    换查询逻辑!!!!!!!!  

            改进逻辑:   用in代替like!  这是我最不愿意用的函数!select * from region where uid in('child1', child2'', 'child3' ···);  但事实就是这样, 你越是不愿搭理的事物,有时候它反而还跟你叫上真儿了, 非它不方便! 关键是人家与索引不冲突哇!!!

        结论············  用index+in()  代替原来的万能like(%)、查询速度成倍提升! 但是随之而来的是插入数据的时间变长; 看你的侧重了、

        我们经理常说, 做一个项目就像扒一层皮,   我此时想说, 做一个项目就像杀我一次, wqnmlgbd,, 呵呵  但是学到的东西远不是书本中能提供的了的、 

        人说痛并快乐着, 那就是傻子, 痛的时候停下来休息下, 养养伤, 伤好了才有心情去寻找快乐嘛  对不对? 

        我自己很喜欢初涉IT泥潭的一句话, 也是我自己凝练的······················

            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

            ~~~~~~~~~~~~~~~~~~~~~~~~唯有压力才能突破, 才能距破茧成蝶之日更近一步~~~~~~~~~~~~~

            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~     

展开阅读全文

没有更多推荐了,返回首页