听朋友一个需求,根据A库的t1表数据修改B库t2表的数据,有唯一对应关系。
直接采用java代码一条一条去update,一段程序的优化之路。
最初代码如下:
程序执行10条发现没问题,开始执行100条,发现太慢了。感觉串行去修改效率不高,考虑多线程。直接上多线程代码
emmmm 是多线程,也有shutdown,代码codeview无误。执行结果太慢了。然后想看看是不是多线程,打印了执行线程id,结果发现怎么是串行的。
原来执行还是单线程,代码位置有误,for循环应该放道提交任务的外面,继续修改
打印结果是多线程,happy,解决了。执行300条数据,执行时间居然3分钟,一分钟更新100条,40万需要……
再看也看不出有什么需要修改的地方,想想修改mysql的连接数据,修改线程池数量大小,修改内容添加索引,结果没有任何变化。
看到update想到为什么要先查询在去修改呢。于是去掉查询,执行300条瞬间完成。哇……查询这么耗时。
优化思路:
1、能并行处理任务就不要串行处理
2、添加索引,修改程序连接数据的连接数
3、扩大线程池大小
4、去掉不必要的查询,减少和数据库交互
最终代码如下:
public void executor(){
int pageSize = 8000;
int pageIndex = 1;
while (true) {
int start = (pageIndex - 1) * pageSize;
final List<Results> resultsList = resultsDaoMapper.limit(start,pageSize );
if (CollectionUtils.isEmpty(resultsList)){
return;
}
final ExecutorService executorService = Executors.newFixedThreadPool(1000);
for (Results results: resultsList){
executorService.submit(new Runnable() {
@Override public void run() {
UserPo userPo = new UserPo();
try{
userPo.setPhone(results.getUsername())
userPo.setSalt(results.getSalt());
userDaoMapper.update(userPo);
}catch(Exception e){
//results.getUsername()输出
}
}
});
}
executorService.shutdown();
try {
executorService.awaitTermination(10, TimeUnit.MINUTES);
} catch (InterruptedException e) {
}
}
//结束
}