1. 问题背景
在项目开发中,我们需要实现一个复杂的分页查询功能,涉及大量 IP 地址数据的处理和多表关联。在我接手这个项目标时候,代码是如许的
要知道代码内里的 ipsList 数据大概几万条甚至更多,如许拼接的sql,必然是要内存溢出的,一味地扩大jvm参数不是办理问题的根本
2.优化进程
2.1. 暂时表处理
为相识决内存溢出的问题,我实验使用暂时表,分批次处理ipsList数据
固然办理了栈溢出的问题,但是数据量太大,频繁的io,单次查询的时间也大概在9秒左右,batchSize的值也不是越大越好,但是不管实验多少,单次查询的时间最快也需要八秒多,如果我是用户,我以为这是不能忍受的,但是对于程序员来说,能跑就行,想要快,那是别的的价钱,不外谁让我善良体贴又温柔呢,于是分析了一下,泯灭时间的这一步无非是overhauledPlanMapper.insertBatchWithParams(params);
这个io操作,如果能异步并发处理的话,是不是就能办理查询慢的问题了,究竟这也不涉及到共享变量的修改
(写到这里,手有些凉,于是插进了口袋,糟糕,早上买的两个鸡蛋忘记吃了,这一天天的上班把我脑子都上坏了)
2.2 异步并发编程
到这里我以为已经很完美的办理了这个问题了,等我摆设上去运行的时候
我很无解,仔细研究了代码,我不明白为什么会出现暂时表不存在的问题,看了日志我发现在insert语句还没有完成之前表就已经被drop了,一开始我以为是线程安全问题,于是我开始实验加锁,使用synchronized(TEMP_TABLE_LOCK)全局锁,使用事件,确保所有操作在同一个事件中举行,但是不管我使用哪种方法,依然会存在暂时表不存在的问题,这让我很百思不得其解.
在翻阅了很多资料之后我终于发现了问题所在,问题就出在暂时表上,让我们看看暂时表的特点
生命周期:
可见性:
看到这我终于明白了为什么会出现这个问题了,我得表是在主线程创建的,由于 暂时表仅在当前会话可见,不同会话间不能共享,所以子线程在并发插入的时候无法访问主线程创建的表,我悟了,但是我又触底反弹了,舔狗的剧本里舔狗才是主角,额.....不美意思,走错片场了.
到这问题就简朴了,我只需要把暂时表修改成普通表就行了,只需要删除TEMPORARY关键字就行
到这里大功告成,已经完美办理了暂时表不存在的问题,摆设运行,实验了多个batchSize的值,最终发现当batchSize=1000左右的时候,查询服从最高,单次查询时间在1.8秒左右
但是如果batchSize设置成固定的值的话,我以为大概会出现个问题,如果ipsList的数量太大,就是批次太多,大概会有上百个批次,也就意味着大概会出现同时并发上百个线程,而你的cpu又不能同时负担这么多线程的话,就会出现线程阻塞,服务就会卡死,于是再优化一波
这是最终的版本,写解释呢并不是给我看,我是怕背面接手的人看不懂,究竟每次改别人的代码我都是边骂边改的,口吐芬芳,鸟语花香,如芒刺背,如坐针毡,如鲠在喉.......
固然说这只是一个简朴的查询,但是这中间优化的过程还是挺有意思的,思想和逻辑可以运用到其他项目中的各个业务中,对我的开导还是挺大的,所以记录一下,此篇文章为中午苏息时间所写,以此共勉........
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |