接口压测分析
现在我们来压测一个获取用户信息接口,这个接口会涉及到数据库的数据查询。我们的项目是部署正在应用服务器上面的,因此我们需要同时监控应用服务器和数据库服务器。
那么下面我们来看一下tomcat的这台服务器,cpu的使用率并不高,包括网络、磁盘IO等都没有什么问题。
下面我们在来看一下数据库的服务器,可以看到cpu已经高达100%了。存在非常明显的性能问题。那么我们可以初步分析,问题可能出现在数据库查询上面,因为我们只用了10个并发,这个并不算多。
数据库性能分析-索引
下面我们来回看一下我们前面压测所出现的现象:
TPS很低,响应时间很长,数据库服务器cpu很高(接近100%),应用服务器负载比较低。
通常我们数据库服务器cpu很高,一般都是因为SQL执行效率低导致的。可能有三方面原因:
- 1、数据库表中缺少必要的索引;
- 2、索引不生效;
- 3、SQL不够优化;
关于索引
索引是对数据库表中一列或多列的值进行排序的一种结构,存储了表中的关键字段,使用索引可快速访问数据库表中的特定信息。
那么我们初步定位是由于SQL导致的性能问题,我们是不是可以对SQL进行监控呢?
我们需要查询下mysql是否开启了慢查询
1|show variables like '%slow_query_log%
我们可以看到慢sql并没有开启
下面我们需要对mysql配置慢查询。具体如何配置,可以查看我的这篇博客:https://blog.csdn.net/weixin_42274846/article/details/128032102
下面我们开始对SQL进行监控,进入到mysql存放的日志路径下(之前慢查询配置中有返回具体的日志路径),因为压测前,我们并不知道里面的数据是不是我们之前压测的数据,所以我们输入 > 文件名称,如 > mysql-slow.log
来清空里面的数据,然后再进行压测。
压测过程中,我们可以看到日志中出现了大量的SQL日志,那么我们可以确定再压测的过程中,这些SQL的响应时间已经超过了我们原先配置的预期值了。
那么我们已经知道有哪些慢SQL了,接下来应该如何对这些SQL进行分析呢?
在/usr/bin目录下,使用mysql自带命令 mysqldumpslow 。这个工具下面提供了一些参数,关于参数的介绍,可以再我之前的慢sql配置的博客中,有介绍。
那么我们下面用如下命令进行分析:
1|mysqldumpslow –s at -t 5 mysql-slow.log
// 显示出耗时最长的5个
上面我们可以看到返回了一条SQL。我们来具体看看这些返回的数据到底是什么含义:
- Count:顾名思义,就是这条SQL执行的次数
- Time:SQL执行的时间,这里我配置的慢SQL时间是(0.05s),这里0.07s相当于是70ms,可能很多人会觉得70ms算短的,时间确实很短,但是对于一个接口而言,数据库就用到了70ms,那么整个http请求,包含业务逻辑、网络因素、以及前端渲染等时长,最终用户所得到的响应是非常长的。
- 下面显示了超时的SQL
我们可以看到这是一条非常基础的查询SQL,那么我们已经知道SQL非常慢了,具体我们应该怎么去做分析呢?我们mysql提供了explain
方法。
explain的简介
mysql中可以使用explain这个关键字来获取(查询)sql语句的查询执行计划的。使用explain关键字,可以模拟mysql优化器执行的sql语句,从而知道mysql是如何处理sql语句的。通过explain可以分析查询语句或表结构的性能瓶颈。
explain的作用
①、查看表的读取顺序
②、数据读取操作的操作类型
③、查看哪些索引可以使用
④、查看哪些索引被实际使用
⑤、查看表之间的引用
⑥、查看每张表有多少行被优化器执行
打开navicat
数据库连接工具,做过测试的朋友,几乎每个人电脑都会安装这个工具。下面我们输入这条SQL语句,再SQL前,加上 EXPLAIN
, EXPLAIN指的是执行计划。
我们的SQL为什么执行的慢的,主要查看的就是结果的type。Type指的是我们对索引的使用情况。下面是关于MYSQL执行计划 TYPE值的关系:
性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
性能在 range 之下基本都可以进行调优
那我们可以看到上面的SQL查询,他返回的type值为all,这个性能是非常差的。通常出现all的情况下,主要是因为该表没有建索引导致的。下面我们打开该表的表设计可以看到果然表中没有建索引。
给他加索引,通常索引是加sql where后面的条件。(通常发现是索引问题,可以让开发通知DB去加就行。)
下面我们把这个索引值给加上。上方我们可以看到有个索引类型,通常工作中常用的类型有NORMAL
和UNIQUE
。选择类型需要根据业务类型也决定,UNIQUE 是唯一值,如果说我们选择了UNIQUE
,那么之后user_name就是唯一的,之后插入相同的user_name,数据库就会报错。
这里我们公司的业务是user_name是唯一的。所以选择 UNIQUE
。后方的索引方式,默认都是选择BTREE
。
保存之后,我们再来看一下sql的执行计划。我们可以看到直接变成const了。从最差变成了最好。
现在我们加了索引,再重新做一下压测。我们来看一下压测的数据。性能明显提升上去了,由原先的40个tps到了400多,响应时间也从原来的200ms变成了20ms左右。
下面我们再来看一下数据库服务器,cpu的空闲率现在也变成了70%左右了。
我们再来看一下应用服务器,但是现在压力到了应用服务器上面。通常情况下应用服务器如果性能不好我们可以进行扩容,但是如果是数据库服务器性能问题,会比较麻烦,这个涉及到了架构问题。
结果总结,
如果我们的SQL是全表扫描会非常影响服务器的性能,直接导致数据库服务器的cpu飙升。因此可以得出索引的设置,直接影响到了我们的性能,索引的选择相差也是非常大的。