85251742 2014-08-30
好久没有动博客了,今天有时间把前段时间问题的解决思路总结一下。欢迎一起讨论。
应用端:
1.在多线程计算情况下汇总计算结果,必免不了要去重。比较常见的方法是重写hashCode和equals方法,其计算速度取决于hashCode方法的逻辑,需要根据业务逻辑,尽量使hashCode的值从不同的业务维度来累加。比如去重对象Object有四个维度,需把四个维度Object.A,Object.B,Object.C,Object.D四个维度都计算。这样的优势在于减少equals方法的调用。equals方法也有讲究,把耗时少,容易计算的逻辑放在前面,也可以
提升去重的效率。
2.数据集合空间的及时释放。每个线程执行完业务逻辑以后,最好把任务线程的数据集合释放空间(比如ResultSet.clear()),否则一段时间以后内存就满了,比较奇怪的一点是在JConsole中主动执行GC也不会回收内存。后来想了想是否有其它地方在引用此数据集合以及每个任务线程是否做到了自身独立。经排查没有发现可疑的地方。
3.明细表ID如何从汇总表中读取。如果是独立的表,可以直接使用sequence。但是因为汇总表的记录先生成,所以不能直接去读取。如果每次插入汇总表之前,先去数据库中获取到当前sequence的值,这样的劣势是访问库的次数太多。用临时表的方式可以解决这个问题,不过太麻烦。后来想到了用AtomicLong,先获得表的总行数对AtomicLong进行初始化,自增AtomicLong的值作为ID,这样达到不会重复。不过前提是只有一个应用在保存,否则不能保存唯一性。
4.GC策略的选择。后台计算的节点使用并行(UseParallelGC)方式,对计算提升比较大,因为观察JConsole可以看到新生代的内存变化浮动是很大的,(配置的是80G,短时间内会频繁发生几十G消耗)。因为并行采用拷贝复制的内存回收方式,对于大内存来讲是相当有效的。如果是WEB服务端的回收机制,需要配置成CMS(并发)方式,该策略使用压缩回收,不会因为GC而停止应用的执行。
5.其它业务逻辑的小算法。因涉及到具体的业务逻辑,在此不展开介绍了,不过解决这些问题离开不了数学知识及javacollection使用的熟练成度。
数据库端:
1.分区方式建表,并指定其数据空间。因表的数据量有上亿条,并且周期性的增长,这里使用oracle11G的新特性,例如每隔7天建一个分区:NUMTODSINTERVAL(7,'DAY')。
2.索引的建立,并指定其索引空间。需要结合前台查询的逻辑进行分析。是否需要组合索引还是单索引。需要花时间进行尝试。其间发现建了索引,但查看执行计划,SQL语句并没有走到实际预期的索引,后来发现是因为表的统计信息未收集完成,orcale有自动信息收集的机制,可以一段时间以后再尝试查询。