如何建设网址导航网站,腾讯竞价广告,个人网站的设计及实现,兰州网站建设推荐q479185700上墙hello#xff0c;大家好#xff0c;我是灰小猿#xff01;
平常在开发过程中#xff0c;时常会遇到一些复杂查询或复杂业务#xff0c;导致接口出现性能问题#xff0c;基本上每一个程序猿在工作中都离不开对接口性能的调优#xff0c;
今天我就在这里记录一下最近在实…hello大家好我是灰小猿
平常在开发过程中时常会遇到一些复杂查询或复杂业务导致接口出现性能问题基本上每一个程序猿在工作中都离不开对接口性能的调优
今天我就在这里记录一下最近在实际开发中对于一个业务和查询都复杂且数据量较大的查询性能优化的心路历程也算是对自己本次优化过程做一个总结对后面的开发起到一个帮助作用
接口优化前
5W数据的业务处理ApiPost请求耗时约2s前端页面请求直接不用说了加上界面渲染直接干到3s多而且这个接口还是查询比较频繁的接口。显然这样子的接口性能肯定是不行的。
接口优化后
5W相同数据优化后前端请求耗时平均约0.2s左右接口查询刷新基本不用等待达成要求
下面我就对本次接口优化的过程做一个总结
一、避免重复的查询sql调用
一般优化性能的第一步就是看你的代码是否存在明显的逻辑错误或重复调用一般来说性能耗时主要就是体现在两个地方
业务复杂导致的业务处理耗时数据库查询耗时
想要知道整个代码块中具体耗时体现在哪些地方就需要对功能模块分别加日志输出执行时间。
在对代码结构进行盘查的过程中发现存在一些基本相同的sql被重复调用了这就导致了接口在执行的过程中会不断的访问数据库每一次访问数据库都是一个IO操作重复这样的操作势必会造成耗时增加。sqk的重复调用主要体现在两点上
1方法调用内外同样的表查询被执行两遍
也就是说虽然可能方法内外都需要表中的某条数据但是一般我们只需要在方法调用前执行一次该查询就可以了之后将返回值作为参数的形式传入需要的方法即可这样就可以完全避免sql在方法内外重复执行从而增加查询消耗。
2for循环执行sql查询
这个算是比较基本的问题了通过for循环遍历某些条件再通过这些条件去分别请求数据库操作一定会增加数据库的交互从而增加耗时所以在代码中无论业务大小一定要避免for循环内部重复执行库操作。
可行的操作是先通过stream流等操作拿到所有的查询条件然后对数据库执行批量操作这样只需要一次sql交互就可以将后面想要的数据都给查出来如果需要获取后面再通过map封装一下就可以了。
通过把上面的问题逐一优化之后再去测试代码性能有了明显的提升耗时降到了1.5s左右这也可以算是通过优化业务代码来优化接口性能了。但是这个时间在操作比较频繁的接口来讲用户体验还不算好因此还不能完全满足那就继续对耗时代码进行优化。
二、不要用联表查询
继续对代码执行过程中输出日志看具体的耗时代码这一次发现耗时的代码主要体现在一些联表查询上对于比较复杂的查询在做联表查询时如果连接的表比较多联表使用不当势必也会造成性能问题
因此我将联表查询拆分成单表查询加数据封装的形式经过性能对比发现采用单表的方式比联表查询的性能要优得多通过看了其他的联调查询的耗时也发现都是一样的
因此建议大家在写联表查询的时候如果时间允许可以对比下单表和联表的情况下性能是否有明显差别如果有当然要选择更优的一方。
因此第二步我将耗时的联表查询改成了性能更优的单表批处理方式。
三、常用字段添加索引处理
除了将耗时的联表查询改为性能更优的单表查询外还有一个数据查询比较关键的优化方案就是给常用字段增加索引这个应该也是最快优化查询性能的方法。
比如我们可能在做批量查询时经常会对某一字段执行in条件查询那么就可以给这些常用字段增加上索引来提高查询性能
但是一般来说一张表中的索引个数不建议超过三个而且在使用索引的过程中要注意索引是否真正使用索引是否失效等问题如果可以有效的使用索引那数据库查询的性能也将会有明显的提升。
经过上述优化之后原本2s耗时的接口现在前端请求只需要大约0.6-0.8s左右优化了一倍左右其实效果还是蛮不错的
但是对于对性能要求严格的程序猿们来讲哪怕是0.1s的优化也是对极致性能的追求
因此在做完上面三步优化后我继续对代码输出日志进行分析发现整个执行流程中业务封装的耗时仅占总耗时的百分之三十不到大部分耗时还是体现在了数据查询上这里说明一点我的持久层框架使用的是mybatisPlus因此在数据查询到模型映射的过程中也会存在一定的耗时问题但是这些耗时是你只要使用数据库查询基本上都是不可避免的。
四、增加缓存Redis or 本地
对于数据库查询耗时的问题我又想到能否通过增加缓存来避免直接操作数据库而是通过缓存来获取数据这样不就可以避免数据库查询耗时了嘛经过Redis和本地缓存的对比我最终选择了本地缓存caffeine作为缓存框架具体caffeine的使用后面我会单独出一期使用教程
我采用的方式是针对整个接口中复杂且耗时的库查询采用缓存的形式来存储数据仅在缓存未命中的情况下执行库查询对于通过缓存可以拿到的数据直接从缓存中获取。从缓存中获取数据的时间几乎是毫秒级可以忽略
因此通过增加缓存就在每次查询时完美的避开了耗时的库查询操作将缓存完整的加上去之后再去执行前端请求5W数据的情况下接口耗时从原来的2s多稳定到了0.2s上下性能优化了进10倍至此整个接口也算是优化到了比较满意的地步。
上面是我对最近解决性能问题的一些方法和思路小伙伴们有好的建议或想法欢迎提出讨论
我是灰小猿我们下期见