内容简介:最近接到反馈,客户端偶尔出现接口异常。通过初步的日志排查发现是MySQL的问题,于是针对这次的异常对MySQL进行了一次性能问题追踪和优化。事情搞定后就一直想写一篇总结记录下追踪的过程以及优化的思路,最后在磨蹭了一个星期后有了这遍笔记。(首先说一下问题的状况:客户端反应的状况是最开始怀疑是定时任务的问题,因为业务在后台有很多定时任务,其中不乏对数据库大量数据做聚合操作的任务,有一些任务在实现时没有考虑其对性能的影响,往往会产生间歇性的数据库性能不稳定。但是通过观察发现这次内存飙升的时间间隔并不固定,初步排除
记一次 MySQL 性能优化
最近接到反馈,客户端偶尔出现接口异常。通过初步的日志排查发现是MySQL的问题,于是针对这次的异常对MySQL进行了一次性能问题追踪和优化。事情搞定后就一直想写一篇总结记录下追踪的过程以及优化的思路,最后在磨蹭了一个星期后有了这遍笔记。( 笔记里的数据表名和数据都为事后在本地模拟,可能难以反映出线上当时的真实耗时情况 )
首先说一下问题的状况:客户端反应的状况是 mysql间歇性连接超时。 问题并不能明显地反馈在某个 sql 上,通过查看监控日志,发现 内存间歇性飙升。
最开始怀疑是定时任务的问题,因为业务在后台有很多定时任务,其中不乏对数据库大量数据做聚合操作的任务,有一些任务在实现时没有考虑其对性能的影响,往往会产生间歇性的数据库性能不稳定。但是通过观察发现这次内存飙升的时间间隔并不固定,初步排除是定时脚本的问题。
会不会是慢SQL的问题,由于项目迭代开发速度的问题缺乏很好的质量检测,一般情况下,这个问题是最常出现的性能问题,这次也不例外,第一时间将慢SQL日志调出来查看。然后。。。嗯?这次的慢SQL有点多啊,并且有点繁杂,反应出来就是其中某个表 partner
,跟这个表相关的sql全部被标记为慢SQL。渐渐意识到问题有点严重呀!
然后随便拿出一条慢SQL执行,嗯? 8ms,这是啥慢SQL,这已经要比数据库的绝大多数哦SQL快了。索性在有一次问题复现时根据当时的 [show processlist]() 反馈,发现有会话数量很不稳定,忽高忽低,在内存飙升的延后几秒中内往往会有大量的进程。在案发现场,定位到一个条可疑SQL,(根据进程的状态、执行SQL的时间)。拿出来执行一下,发现确实是慢SQL,然后怀疑是当前内存不足的原因导致的慢SQL,于是将这条SQL拿到写数据库中执行,发现依旧是很慢,于是定位到一个问题,具体是不是它导致了全部问题需要先优化了它再分析,保存了当时的processlist后对这条sql进行优化。
先来看一下这条SQL: select
uid from partners where
id in (1,2,3,"4","5",...)
SQL的结构很简单,就是根据id搜索partners表的uid,其中uid和id都有索引,id为主键。问题SQL找到了下面就是SQL优化三板斧的工作了。
先进一步通过 profiles 来进一步定位问题。
Status | Duration | Block_ops_in | Block_ops_out |
---|---|---|---|
starting | 0.000046 | 0 | 0 |
checking permissions | 0.000027 | 0 | 0 |
Opening tables | 0.000049 | 0 | 0 |
init | 0.000038 | 0 | 0 |
System lock | 0.000027 | 0 | 0 |
optimizing | 0.000028 | 0 | 0 |
statistics | 0.000037 | 0 | 0 |
preparing | 0.000030 | 0 | 0 |
executing | 0.000025 | 0 | 0 |
Sending data | 0.146700 | 64 | 1144 |
end | 0.000077 | 0 | 0 |
query end | 0.000027 | 0 | 0 |
closing tables | 0.000031 | 0 | 0 |
freeing items | 0.000049 | 0 | 0 |
cleaning up | 0.000028 | 0 | 0 |
可以很清楚的看到,语句在Sending data模块消耗太多时间,并且进行了大量的IO操作。sending data表示收集+发送数据,通常产生的情况有一下几种:
- 存在大字段或返回数据量过大导致数据传输过慢。
- sql可能没有走索引,扫了大量数据,从大量数据中找这一条记录。
- 数据库服务器网络问题。
由于SQL返回结果只有1条,且不存在大字段,很容易定位到是数据收集阶段的问题,于是怀疑到了索引上。
再使用 explain或desc 看一下执行计划:
type | possible_key | key | extra |
---|---|---|---|
index | PRIMARY | idx_uid | Using where; Using index |
发现并没有使用主键也就是id索引。于是问题已经很明显了。最后给出优化方案。
在Mysql中id字段为int型,where条件中使用 in(1, 2, 3)
是可以命中索引的,使用 in("1","2","3") 通过mysql优化器的优化为int型后也可以命中索引,但当两者混用时,mysql不会对它进行优化,导致索引失败。后面就是业务层的事情了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 性能优化第一课:性能指标
- 【前端性能优化】vue性能优化
- Golang 性能测试 (2) 性能分析
- 【前端性能优化】02--vue性能优化
- Java性能 -- 性能调优标准
- Java性能 -- 性能调优策略
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
RESTful Web Services Cookbook
Subbu Allamaraju / Yahoo Press / 2010-3-11 / USD 39.99
While the REST design philosophy has captured the imagination of web and enterprise developers alike, using this approach to develop real web services is no picnic. This cookbook includes more than 10......一起来看看 《RESTful Web Services Cookbook》 这本书的介绍吧!