MySQL高CPU占用排查——索引的重要性

划重点:

建表时考虑怎么查询,给必要的字段创建索引可以提升查询效率,减小加锁的范围,降低加锁的时间

使用explain解释sql语句可以查看是否使用了索引

索引不仅仅为了提高查询速度,使用索引避免全表锁可以提高查询、更新操作的效率

最近一段时间涉及的ES的查询任务都变的异常慢,很多定时任务都比原来多出几个小时的执行时间。一直在排查ES的问题,但是没有找到哪个新增的操作会导致ES性能下降。由于有一台服务器部署了2个ES节点和一个mysql,这台服务器的负荷一直以来都比较高,当看到这台服务器高负荷时并没有终点关注。后来,使用top命令查看进程时,发现mysql占用了800%的cpu时间,意识到是mysql的哪个操作出现问题了。排查步骤如下:

  1. show porcesslist

使用show porcesslist,看看有没有长时间执行的任务。发现有好几条查询语句处于sending data状态持续了2000多秒,第一反应就是这个表没有索引。一查表结构果然如此,分析一下查询语句添加索引吧。

问题又来了,添加索引的语句执行了半天没有反应,show porcesslist发现语句正在获取锁。无奈至下把关于这个表的所有任务都kill掉,然后再创建索引,然后成功了,添加索引后原来执行30分钟的任务只需要5秒。

回过头来再分析一下原因,我挑了设计改表的2个sql语句,如下:

UPDATE 
      `iptv_alarm` 
    SET
      olt_ip = '{ip}' 
    WHERE dev_code = '{code}'
    AND olt_ip is NULL
SELECT 
      * 
    FROM
      `iptv_alarm` A 
    WHERE eventtime = 
      (SELECT 
        MAX(eventtime) 
      FROM
        `iptv_alarm` B 
      WHERE A.dev_code = B.dev_code 
        AND A.clearancereportflag = 0 
        AND A.dev_type = 2 
        AND gte_five = 0 
        AND rk_time > '{start_time}' 
        AND rk_time <= '{end_time}' 
        AND dev_code IN ({olt_list})) ;

上面一个是更新语句,下面一个是查询语句。由于没有索引,每次查询时创建共享锁(表锁),每次更新时创建排它锁(表锁)。由于两个语句执行都比较频繁,mysql就疲于申请锁、加锁、释放锁之间,cpu都被它吃了。再看添加索引后,我新增了rk_time,dev_code两个字段的索引,实际查询时只使用了dev_code的索引。有了索引之后,查询和更新语句都可以申请行锁,而不用对整个表加锁,另外查询效率也快了,整体效率自然提升上去了。

另外,整个表只有3万条数据,数据量并不大。所以无论数据量大小,建表时一定要考虑好整个表要怎么使用,创建必要的索引。

推荐阅读:

MySQL 表锁和行锁机制

你可能感兴趣的:(MySQL高CPU占用排查——索引的重要性)