接口调优:从2s到200ms的心路历程分享

hello,大家好,我是灰小猿!

平常在开发过程中,时常会遇到一些复杂查询或复杂业务,导致接口出现性能问题,基本上每一个程序猿在工作中都离不开对接口性能的调优,

今天我就在这里记录一下最近在实际开发中对于一个业务和查询都复杂,且数据量较大的查询性能优化的心路历程,也算是对自己本次优化过程做一个总结,对后面的开发起到一个帮助作用,

接口优化前:

5W数据的业务处理,ApiPost请求耗时约2s,前端页面请求直接不用说了,加上界面渲染,直接干到3s多,而且这个接口还是查询比较频繁的接口。显然这样子的接口性能肯定是不行的。

接口优化后:

5W相同数据,优化后前端请求耗时平均约0.2s左右,接口查询刷新基本不用等待,达成要求!

下面我就对本次接口优化的过程做一个总结,

一、避免重复的查询sql调用

一般优化性能的第一步就是看你的代码是否存在明显的逻辑错误或重复调用,一般来说,性能耗时主要就是体现在两个地方:

  1. 业务复杂导致的业务处理耗时,
  2. 数据库查询耗时,

想要知道整个代码块中具体耗时体现在哪些地方就需要对功能模块分别加日志输出执行时间。

在对代码结构进行盘查的过程中,发现存在一些基本相同的sql被重复调用了,这就导致了接口在执行的过程中会不断的访问数据库,每一次访问数据库都是一个IO操作,重复这样的操作势必会造成耗时增加。sqk的重复调用主要体现在两点上:

(1)方法调用内外同样的表查询被执行两遍

也就是说,虽然可能方法内外都需要表中的某条数据,但是一般我们只需要在方法调用前执行一次该查询就可以了,之后将返回值作为参数的形式传入需要的方法即可,这样就可以完全避免sql在方法内外重复执行,从而增加查询消耗。

(2)for循环执行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倍,至此,整个接口也算是优化到了比较满意的地步。

上面是我对最近解决性能问题的一些方法和思路,小伙伴们有好的建议或想法,欢迎提出讨论!

我是灰小猿,我们下期见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/117872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

angular2+ 集成系统利用服务作为模块通信中间件

模块间通信的话angular2可以使用Input() 和 Output()进行父子组件间通信 例如 父组件html <app-input-output [item]"currentItem" (deleteRequest)"crossOffItem($event)"> </app-input-output>子组件ts export class ItemDetailComponent…

【IDEA查看一个jar包的依赖】

首先install,打jar包 重新创建一个项目 选中刚才的jar包 在这个包下就能看到jar包的依赖了

ES SearchAPI----Query DSL语言

文章目录 Getting Startedmatch_all查询全部sort排序from\size分页_source指定字段 match匹配查询match_phrase短语匹配multi_match多字段匹配range范围查询bool复合查询must必须匹配&#xff0c;可贡献得分must_not必须不匹配&#xff0c;可贡献得分should可有可无&#xff0c…

AnkiPDF Guru软件评测:打开全新学习方式的大门

在当今信息爆炸的时代&#xff0c;如何高效学习和记忆成为了每个人关注的焦点。AnkiPDF Guru软件作为结合了Anki和PDF的学习利器&#xff0c;向我们展示了一种全新的学习方式。本文将以软件的实用性和使用场景为切入点&#xff0c;从专业的角度客观分析和评测该软件&#xff0c…

VB.NET 中使用SqlConnection类连接到Microsoft SQL Server数据库的详细步骤

目录 前言: 过程: 1.建立SqlConnection连接 2.打开SqlConnection连接 3.关闭SqlConnection连接 4.执行SqlCommand命令 5.传递参数 总结: 前言: VB.NET的SqlConnection是一个用于连接到SQL Server数据库的类。在VB.NET中&#xff0c;SqlConnection是一个很重要的类&…

听GPT 讲Rust源代码--library/std(1)

std git:(master) ✗ tree.├── Cargo.toml├── benches│ ├── hash│ │ ├── map.rs│ │ ├── mod.rs│ │ └── set_ops.rs│ └── lib.rs├── build.rs├── src│ ├── alloc.rs│ ├── ascii.rs│ ├── backtrace│ │…

Mysql主从集群同步延迟问题怎么解决

主从复制 复制过程分为几个步骤&#xff1a; 主库的更新事件(update、insert、delete)被写到binlog 从库发起连接&#xff0c;连接到主库。 此时主库创建一个 binlog dump thread&#xff0c;把 binlog 的内容发送到从库。 从库启动之后&#xff0c;创建一个 I/O 线程&#xff…

TensorFlow和Pytorch两种机器学习框架的比较及优缺点

TensorFlow是一个开源的机器学习框架&#xff0c;由Google开发并发布&#xff0c;它被用来构建各种类型的机器学习模型&#xff0c;例如图像识别、语音识别、自然语言处理等。TensorFlow主要有以下几个基本概念&#xff1a; Tensor&#xff1a;TensorFlow中最基本的数据结构&am…

Pillow库(PIL)入门教程

Pillow库&#xff0c;PIL的升级版&#xff0c;一个免费开源的Python图像处理库。 Pillow 库&#xff08;有时也称 PIL 库&#xff09; 是 Python 图像处理的基础库&#xff0c;它是一个免费开源的第三方库&#xff0c;由一群 Python 社区志愿者使用 Python 语言开发而成&#…

创建Secret(手动)

和创建其他类型的 API 对象&#xff08;Pod、Deployment、StatefulSet、ConfigMap 等&#xff09;一样&#xff0c;您也可以先在 yaml 文件中定义好 Secret&#xff0c;然后通过 kubectl apply -f 命令创建。此时&#xff0c;您可以通过如下两种方式在 yaml 文件中定义 Secret&…

数字化营销如何推动企业营收增长?数字化营销要点有哪些?

在数字化席卷而来的时代&#xff0c;企业若想在激烈的市场竞争中脱颖而出&#xff0c;就得紧跟潮流&#xff0c;运用数字化营销手段更快、更准地触达目标客户&#xff0c;从而帮助企业更好地解读客户需求&#xff0c;捕捉痛点&#xff0c;实现精细化营销闭环。 数字化营销如何让…

经典卷积神经网络 - GoogLeNet

GoogLeNet是google推出的基于Inception模块的深度神经网络模型&#xff0c;在2014年的ImageNet竞赛中夺得了冠军&#xff0c;在随后的两年中一直在改进&#xff0c;形成了Inception V2、Inception V3、Inception V4等版本。 Inception块 4个路径从不同层面抽取信息&#xff0…

java版opencv之Javacv各种场景使用案例

文章目录 1.关于Javacv~~2. [官网下载最新OpenCV4.8](https://opencv.org/releases/)&#xff0c;并解压~~ *不一定要安装opencv*~~3. 将opencv的jar包及动态库dll文件引入项目~~4.pom引入javacv库5.测试5.1 图片美颜5.2 图片人脸检测5.3 提取视频中的语音5.4 音视频剪辑5.5 录…

python关于当前时间戳的获取及时间运算

日期和时间在计算机编程中是非常重要的概念&#xff0c;特别是在处理数据、日志记录、计划任务等方面。Python作为一门功能强大的编程语言&#xff0c;提供了丰富的库和内置函数&#xff0c;使得对日期和时间的操作变得简单而高效。本文将介绍一些常见的Python日期时间操作&…

shell脚本实战案例--系统服务脚本

目录 1、源码编译安装nginx 2、分别编写基于RHEL6和RHEL7的脚本。 2.1 RHEL6的nginx系统服务脚本 2.2 RHEL7的nginx系统服务脚本 1、源码编译安装nginx 1.首先关闭防火墙和selinux [rootnode13 ~]# systemctl stop firewalld [rootnode13 ~]# setenforce 0 2.准备环境&…

阿里云核心产品list

计算&#xff1a; 01函数计算&#xff08;Function Compute&#xff09;全托管serverless计算服务&#xff0c;不需要管理服务器等基础设施&#xff0c;只需要编写代码并上传。 02云服务器&#xff08;Elastic Compute Service&#xff09;云计算服务 03GPU云服务&#xff08;G…

java类的动态加载

java类的动态加载 java动态加载的机制&#xff1a; ClassLoader->SecureClassloader–>URLClassLoader–>AppClassLoader loadClass–>findClass(重写方法)–>defineClass(从字节码加载类) 初始化的时候会加载静态代码块 实例化的时候会加载构造代码块、无参构…

45.Redis核心数据结构实战与高性能原理剖析

Redis五种常用数据结构 #redis-cli查看帮助命令 help stringstring 应用场景 //单值缓存 Test public void redisString() throws JsonProcessingException {Jedis jedis pool.getResource();// for (String key : jedis.keys("*")) {// …

单片机设计_RTC时钟(ACM32F403)

一、电路设计 ACM32F403开发板 实现结果&#xff1a;通过串口发送每秒的时间 二、运行结果 三、部分代码 #include "APP.h"UART_HandleTypeDef Uart_Handle;/********************************************************************************* * Function …

Banana Pi BPI-W3(Armsom W3)RK3588开当板之调试UART

前言 本文主要讲解如何关于RK3588开发板UART的使用和调试方法&#xff0c;包括UART作为普通串口和控制台两种不同使用场景 一. 功能特点 Rockchip UART (Universal Asynchronous Receiver/Transmitter) 基于16550A串口标准&#xff0c;完整模块支持以下功能&#xff1a; 支…