记一次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 来进一步定位问题。
mysql

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

  1. 存在大字段或返回数据量过大致使数据传输过慢。
  2. sql可能没有走索引,扫了大量数据,从大量数据中找这一条记录。
  3. 数据库服务器网络问题。

因为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不会对它进行优化,致使索引失败。后面就是业务层的事情了。服务器

友链:https://www.yuque.com/threads...网络

相关文章
相关标签/搜索