场景是这样的:使用in查询数据的时候,in的数量越多,效率越低,所以一个优化的思路是,缩小in查询的数量,用多线程的方式查询缩小数量后in的sql,并行查询。
直接上代码:
public List<UserOrgVO> getCscpOrgInfoByUserId(List<Integer> userIds) {
//List<UserOrgVO> list = innerWorkFlowRepository.batchGetCscpOrgInfoByUserId(userIds);
List<UserOrgVO> list = getInListThread(userIds);
return list;
}
private List<UserOrgVO> getInListThread(List<Integer> userIds){
List<UserOrgVO> resultList = Collections.synchronizedList(new ArrayList<>());
List<CompletableFuture> tasks = new ArrayList<>();
int threshold = 3; // 每个线程最大条数
int threadNum = userIds.size() / threshold; // 线程个数
int lastSize = userIds.size() % threshold; // 最后一个线程的数据条数
//多线程
for (int i = 0; i <= threadNum; i++) {
int start = i * threshold;
int end = 0;
if (i != threadNum) {
end = (i + 1) * threshold;
} else {
end = lastSize == 0 ? start : (lastSize + start);
}
int finalEnd = end;
CompletableFuture<Void> task = CompletableFuture.runAsync(() -> {
List<Integer> tempMsIdList = new ArrayList<>();
for (int j = start; j < finalEnd; j++) {
tempMsIdList.add(userIds.get(j));
}
List<UserOrgVO> temps = new ArrayList<>();
if(!org.springframework.util.CollectionUtils.isEmpty(tempMsIdList)){
//查询SQL
System.out.println(Thread.currentThread().getId() + "in的数量:" + tempMsIdList.size());
temps = innerWorkFlowRepository.batchGetCscpOrgInfoByUserId(tempMsIdList);
}
if (!org.springframework.util.CollectionUtils.isEmpty(temps)) {
resultList.addAll(temps);
}
});
tasks.add(task);
}
CompletableFuture.allOf(tasks.toArray((new CompletableFuture[] {}))).join();
return resultList;
}
其中,只需配置private的方法中的最大线程数参数threshold即可,按照实际需求配置,此时我配置的参数是3,即每次in的数量是3个,测试userIds的数量是8个。
打印的结果如下(sql日志忽略):