记录一次后端接口性能优化操作
线上查询卡券接口,列表挺快,点击详情,加载完成后竟然需要三秒,而且里面就只有三条数据,感觉到很是惊讶,着手开始分析
1.mysql的慢sql优化
已经定位到慢sql了,线上explain了一下,如下图,很显然a表全表扫描了21万条数据,没有走任何索引,还有j表和z表也是全表扫描。
看了下,e表是个单独的表,给相应字段加上索引后就好了,但是j表和z表是个临时表,是group by 然后查询出来的,如下图所示,z表之所以全表扫描,是因为它先group
by之后然后再去left链接,确实是把整个表查询了一遍,我们应该根据业务参数把z表减少然后再去左链接,所以我们应该加个条件过滤cooc.xxxxxid=#{xxxxid},xxxxid为业务参数,同样j表也是group by 语句,我们也要给他加个条件过滤,才能走索引,缩小范围然后再去left连接,查询会变快
java代码优化
sql查询出来的数据,会有多条数据,后去格式化了,这个格式化是并行的,我把他做成了异步并行就快多了。
List<xx> parallelStreamList = resultList.parallelStream().map(bean -> {
xx cardbean = new xx();
transferToXXXX(bean, cardbean, status);
return cardbean;
}).collect(Collectors.toList());
看日志可以知道parallelStream使用的如下线程组
ForkJoinPool.commonPool-worker-2
ForkJoinPool.commonPool-worker-3
ForkJoinPool.commonPool-worker-4
因为用了并发后,查询出来的集合已经不是有序的了,需要重新排下序:
cardgameBeanList = parallelStreamList.stream().sorted(Comparator.comparing(Bean::getOrderbydate,Comparator.reverseOrder()).thenComparing(Bean::getOrderbystatus).thenComparing(Bean::getId,Comparator.reverseOrder())).collect(Collectors.toList());
排序这里要注意一下,Comparator.reverseOrder() 不能写成 Comparator.comparing(类::属性一).reversed()。否则会有问题,因为List.stream().sorted(Comparator.comparing(类::属性一).reversed()); 是先以属性一升序,然后对结果集进行属性一降序,而List.stream().sorted(Comparator.comparing(类::属性一, Comparator.reverseOrder())); 是以属性一降序。
总结
优化完之后,接口反应时间从3秒变到0.2秒以下,后面查询出来得数据放缓存就更快了,
还得继续努力!!!