一、问题场景
之前做过一个模块的功能,但是实现功能之后存在性能问题(4万条数据100个并发的时候会很卡,页面响应会很慢),经过一系列的排查,最后终于解决了这个问题,现在想起来还是记录一下解决过程,避免下次踩坑,也给碰到类似问题的朋友提供一个思路(前三步是记录自己解决问题的过程,只想了解springboot+shiro+ehcache使用的朋友可直接到第四步)。
二、功能描述及表结构
任务列表的功能主要是一个树形的展示,点击父级要展开子集。而且还有一个需求(就是这个很坑的需求导致的头疼)就是模糊查询(还有很多筛选条件)的时候查出符合条件的父级和子级,如果子级满足条件,则找出它的父级在页面显示,子级要展开。
三、爬坑之路
坑一、
最开始的时候采用的方法是先找出符合条件的父级id集合,然后再去数据库中查询符合条件的父级,带上分页条件,最后再循环查出各个父级的子级一起拼装后返回给前端。这样虽然也实现了功能,但是有一个问题就是在查询符合条件的父级id的时候,不可避免的出现全表扫描的情况,导致查出的数据量特别大,从数据库中查出来再放到集合中也是需要时间的,所以影响性能。还有就是查询出符合条件的父级之后,需要循环父级集合去查询子级,频繁连接数据库也会很慢。
坑二、
后面的想法是能不能通过只连接一次数据库将所有符合条件的数据都查出来,父任务和子任务的数据存在一张表里,用super_id关联,经过sql的书写发现是可以实现的,思路就是表的left join连接。但是由于表中存在处理人id和创建人id,要关联用户表去查询人名,所以在多并发的时候依然会影响性能,数据库连接会爆满。除此之外,也并不能满足关于筛选条件查询子级并显示父级的需求,所以,这种方案也不行。
解决办法:其实有了前两步的爬坑,对解决性能问题也有了一定的思路。一是尽量减少与数据库之间的交互,二是尽量避免全表扫描,尽量不要一次查询大量数据,三是避免sql语句中出现大量的连接查询。基于这几种思路,关于用户的数据每天只更新一次,所以可以将它放在缓存中,不用每次去查询用户数据。而对于需求中条件筛选出父级和子级也可以在获取父级之后获取父级下所有的子级(数据不会太多),然后再根据父级id去匹配(不必循环去查,多次连接数据库)。
四、springboot+shiro中使用ehcach缓存
4.1 引入依赖
<!-- ehcache 缓存 -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.2</version>
</dependency