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 表锁和行锁机制

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 索引 数据库中的查询操作非常普遍,索引就是提升查找速度的一种手段 索引的类型 从数据结构角度分 1.B+索引:传统...
    一凡呀阅读 3,045评论 0 8
  • MySQL不权威总结 欢迎阅读 本文并非事无巨细的mysql学习资料,而是选择其中重要、困难、易错的部分进行系统地...
    liufxlucky365阅读 2,677评论 0 26
  • MySQL 的加锁处理分析 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题。我在工作过程中,经常会有...
    meng_philip123阅读 800评论 0 12
  • 文章导读: 累兮,累兮,要死兮...... 本文解决问题: 1、表级锁定(读锁、写锁) 2、行级锁定(共享锁、排他...
    创造new_world阅读 655评论 0 1
  • 五笔简明教程4 - 简码和词组的输入 简码的输入 为了更高效的输入, 对于常用汉字, 只取其编码的1, 2, 或3...
    wongFan阅读 598评论 0 2