记一次mysql查询慢的优化历程

Posted 公号运维家

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了记一次mysql查询慢的优化历程相关的知识,希望对你有一定的参考价值。

记一次mysql查询慢的优化历程_sql

 

有一个项目,代称​​cc​​,用了我们公司的产品,单表数据量在200万左右。在做业务操作的时候,点击一下按钮,需要等待2~3分钟。及其难以忍受,特此让我们修改。

PS:涉及的一些​​sql​​命令,简化了很多,不能暴露线上信息。

第一反应

当收到这个问题的时候,第一反应就是确定下到底是后台数据查询慢,还是前端数据渲染慢,亦或者是网慢,那么如何排查呢?

询问客户使用了产品的哪个功能,然后自己模拟一下,并使用F12,追踪下总的时间,是否如客户所说的时长;

定位问题

结果,果然,点击一下然后就开始了漫长的等待,竟然真的需要2~3分钟,完成一个业务流竟然需要10分钟(该业务流需要多次点击菜单处理数据)。

验证客户所说为真。

和网速没关系;

那么接下来验证下是前端还是后台慢;

看下​mysql​​数据库的慢​​sql​​​记录,是否存在长时间的​​sql​​语句。

如果​​mysql​​​没有配置慢​​sql​​记录,那么首先我们要进行如下配置:

vim /etc/my.cnf
# 在 [mysqld] 模块中
slow-query-log=On
slow_query_log_file="/data/mysql/localhost-slow.log"

配置完毕之后,需要重启下​​mysql​​服务。

systemctl restart mysqld.service

而后再次模拟​​cc​​​客户反馈慢的地方,运行完毕之后,看下存储慢​​sql​​文件的地方,里面是否有数据;

vim /data/mysql/localhost-slow.log

果然有,而且时间和前端展示的总时间差不太多,说明响应慢的问题,一大半的原因是因为数据库慢所导致的。其他的就是前端数据渲染慢+服务中转+网速问题了。

解决思路

数据库​​sql​​慢的思路:

首先我们需要找到所有的慢​​sql​​​,找到之后,第一反应应该是查有没有配置索引,有没有添加索引,使用​​explain + sql​​ 的方式来查看,例如:

explain select (*) from ceshi_1;

在展示的信息中,各个参数含义如下:

  • id:选择标识符
  • select_type:表示查询的类型
  • table:输出结果集的表
  • partitions:匹配的分区
  • type:表示表的连接类型
  • possible_keys:表示查询时,可能使用的索引
  • key:表示实际使用的索引
  • key_len:索引字段的长度
  • ref:列与索引的比较
  • rows:扫描出的行数(估算的行数)
  • filtered:按表条件过滤的行百分比
  • Extra:执行情况的描述和说明

根据​​possible_keys​​​和​​key​​即可看到是否配置和使用了索引,如果没有就添加,如果有就检查其他问题。

前端慢的思路:

需要看下前端资源是否进行了压缩传输,以及网速问题;

大概率情况下,网速一般是不需要解决的,除非说这个项目是刚上线就特别慢,这种情况才需要解决网速问题,所以我们只需要看下前端资源是否进行了压缩传输即可。

前端一般使用的是​nginx​;我们看下是否进行了如下配置:

gzip on;
gzip_buffers 32 4k;
gzip_comp_level 2;
gzip_min_length 300k;
gzip_types text/plain application/x-javascript application/javascript application/xml text/css text/javascript image/jpeg image/gif image/png;
gzip_disable "MSIE [1-6]\\.";
gzip_vary on;

以上内容,应该配置在​​nginx​​​中的​​conf/nginx.conf​​​文件中的​​http/server​​​中的​​listen​​参数下;

然后重新加载下​​nginx​​的配置文件,让其生效,使用如下命令:

./sbin/nginx -s reload

最常见的解决方式就是按照上面的来,一般都能解决。

但是

但是

但是

但是

但是

我这里不好使,为什么呢?往下看。

实际解决方案

上面不是说了嘛,总的来说,慢的有两个地方,一个是​​sql​​​查询慢,还有一个就是前端加载慢(有部分影响)。前端就按照上面的解决没问题,但是​​sql​​就不太行。

为啥呢,因为程序里面实现某一功能的​​sql​​​,咋说的,写的有点儿烂,怎么个烂法呢,跨表查询+嵌套查询+​​group by​​​+​​limit​​​+​​like​​​+时间范围查询。就导致了虽然这个​​sql​​中涉及的每个表的使用字段都配置了索引,但是并没有命中,相当于无效了,而且,还不好弄。

当然了,最好的方式是让程序修改里面定义的​​sql​​文件嘛,但是嘛。。。懂的都懂。

最后,通过在​​mysql​​​中添加缓存,这个缓存的作用是什么呢,就是说,当你执行了一条​​sql​​,比如是:

select a,b,b from test_1 where time = 2022-07-27;

你第一次执行这个命令的时候,​​mysql​​​的缓存会把这个​​sql​​和结果存放到缓存中。

只要你涉及到这个查询的数据没有变化,那么你后面再次查询的时候,就不执行查询了,而是直接把缓存中的这个结果返回,这样子就大大减少了查询时间。

怎么配置呢,还是需要修改​​mysql​​的配置文件:

query_cache_size=2048M  # 缓存大小
query_cache_type=1 # 开启缓存

然后重启下数据库;

systemctl restart mysqld.service

当然了,也可以使用​​global set​​的方式临时进行修改。

这样子添加完之后,只有第一次访问慢,后面就非常快了。

通过上面的操作之后,点击菜单的时间从2~3分钟,优化到了14秒左右,客户还是不是很满意,因为他们需要操作的业务量还是挺大的。

那么有没有别的办法呢,再次研究程序里面定义的​​sql​​,看看是否能通过添加联合索引,或者其他索引的方式来优化,你别说,还真的让我发现了一个索引,添加完毕之后,时间再次砍半,由14秒,再次缩短到了7秒左右,这个时候客户终于临时接受了,并发函让我们继续整改。

我们也承诺会进行排期优化​​sql​​,并及时上线。

事情也就到此为止告一段落了。

总结

遇到这种数据库慢的情况,无非就是先定位问题,然后再根据情况来优化,大概率是​​sql​​本身的问题,上线之初可能没有进行审核,只是为了上线而上线了,测试数据也就几百几千条,完全没有压力测试吧。

这个处理方式,仅供参考,不可能所有的都可以按照这个方式来处理,你如果有更好的方式,欢迎通过公众号“运维家”,来我的WX来和我交流。

至此,本文结束。 

更多内容请转至VX公众号 “运维家” ,获取最新文章。


------ “运维家”  ------

------ “运维家”  ------

------ “运维家”  ------


临武县运维工程师培训,温州运维工程师,通达oa实施运维工程师,呼叫中心运维工程师面试

腾讯idc运 维工程师面试,运维工程师samba,运维工程师的行业是什么,

运维工程师的来历,运维工程师好找嘛,运维 工程师出入,运维工程师自学可行


以上是关于记一次mysql查询慢的优化历程的主要内容,如果未能解决你的问题,请参考以下文章

记一次mysql多表查询(left jion)优化案例

记一次MySql优化问题

记一次神奇的MySQL查询经历,group by慢查询优化

2022年记一次慢查询优化指南,MySQL 优化学习第9天

记一次数据库查询超时优化问题

多数据库适配 | 记一次数据源从Oracle到MySQL兼容切换历程