通过内存去重替换SQL中distinct,优化SQL查询效率
一、背景
运维同事收到了生产环境的一条慢SQL告警,执行时间达到了10+秒,分析了业务场景,属于正常查询业务,而且SQL语句是上个版本新增的需求,于是在慧眼上,将SQL链路截图发给了开发进行修复。
二、分析
通过对SQL的执行索引情况分析,发现最后耗时在了distinct阶段,于是就想办法将去重放在内存中进行优化。
三、方案
1:SQL整改
优化前SQL
select distinct color,name .....
优化后SQL
select color,name .....
2:重写hashcode和equals方法
这里用Car举例,只是为了还原业务场景
public class Car{private String color;private String name;@overridepublic boolean equals(Object obj){if(this == obj){return true;} if(obj == null || getClass() != obj.getClass()){return false;}Car car = (Car) obj;return StringUtils.equals(car.getColor(),this.color)&& StringUtils.equals(car.getName(),this.name);}@Overridepublic int hashCode(){return Objects.hash(color,name);}
}
优化后,去掉了SQL中的distinct。
分批查询数据,最后对结果去重。
List<Car> result = new ArrayList<>();
ListGroupUtils.groupListBySize(resultList,1000).forEach(list -> result.addAll(xxDao.findXXX(list))
);
return result.stream().distinct().collect(Collectors.toList());