• 记录一次问题排查


    1. 问题描述:早上刚来上班,业务部门同事反应管理后台无法登录

    2. 问题排查定位

     2.1 服务器排查

      a. 接口是否可以调通:首先自己登陆后台,发现时好时坏,偶尔接口返回【系统忙】。我们系统接口异常调不通会返回系统忙

      b. 服务是否死掉或者假死:连接服务器->查看Java进程,服务正常;排除假死:重启该服务,接口依然调不通

      c. 服务器各项指标:登录阿里云->云服务器ECS->监控,查看CPU、内存、系统负载、云盘iops、网络带宽、连接数,各项指标使用率均在正常范围

     2.2 数据库排查

      a. 数据库各项指标:登录阿里云->云数据库RDS->监控与报警,查看CPU、内存、磁盘空间、iops、网络带宽、连接总数,其它指标正常,唯独CPU使用率达到100%

      b.一键诊断:登录阿里云->云数据库RDS->自治服务->一键诊断,发现CPU使用率偏高,出现了异常慢SQL

        

      c. 慢日志:日志管理 -> 慢日志明细 ,发现有SQL语句耗时7~8分钟,甚至20~30分钟。一条SQL语句执行20多分钟!!!

      d. sql分析:

          

    SELECT you.nick_name,you.mobile,ycu.createtime,ycu.id,ycu.ym_userid, ycu.`status`,cir.coupon_name,cir.use_price,if(ycu.status = '1',ycul.createtime,'') as usedtime,cir.coupon_type as couponType, cir.price,cir.province,ycu.end_time 
    from ym_coupon_user ycu 
    
    LEFT JOIN ym_org_user you on ycu.ym_userid = you.id 
    
    LEFT JOIN coupon_issue_record cir on ycu.coupon_issue_record_id = cir.id 
    
    LEFT JOIN ym_coupon_used_log ycul on ycu.id = ycul.ym_coupon_user_id 
    
    where 1=1 and you.platform_code ='lngpt' 
    
    order by ycu.createtime desc 
    
    limit 10

      可以看出是四表联查,如果有数据量比较大的表,然后关联字段又没有索引将会非常耗时

      用explain分析,即在SQL语句前加上关键字 EXPLAIN然后执行:

      可以看出,4个表中主表全盘扫描,第2、3表关联字段有唯一索引只扫描一行,但是第4张表也进行了全盘扫描。上图是测试环境,数据量较小。

      线上数据表1和表4分别由10多万条和4万多条!然后关联字段没有加索引,导致查询异常慢。

      给表4的关联字段添加索引(ym_coupon_user_id) 后执行EXPLAIN:

      

      可以看出,表4(ycul)也用上了索引,只取出了一行。到此问题得以解决,一条查询语句耗时由20多分钟优化到0.16秒~

     3. 总结:多表关联查询,如果数据量较大查询太慢,被驱动表的关联字段要加索引。

    SQL语句剖析:

    对比加索引前后的 EXPLAIN 结果分析:

    1. ycu表在ycul表未加索引前使用了临时表 (using temporary)

    2. ycul表未加索引是:Using where; Using join buffer (Block Nested Loop),加了索引后是:Using where 

    关键字:using temporary、Using join buffer (Block Nested Loop)、Using filesort

    下面分别进行解析:

    问题1.为啥会出现临时表

    答案:用非驱动表字段排序会出现临时表

      关于左关联查询:首先分驱动表和被驱动表,先去驱动表查询数据,然后以此数据为基准去查询被驱动表。

      驱动表和被驱动表的选择受MySQL优化器的控制,这个比较复杂:

      a、没其它条件的话,选择结果集小的作为驱动表

      b、优先以order by字段所在的表作为驱动表,即时该表结果集较大

      c、即使符合上面的条件,优化器还会优先选择关联字段有索引的表作为 被驱动表

      d、都有索引,则不一定会选择order by字段的表作为驱动表,此时如果数据量差距大选择数据量小的为驱动表,如果数据量差距不明显则选择order by字段的表为驱动表

     **** 到此,上面那条SQL语句就可以明白了,我们再分析下 EXPALIN ,为了方便查看我把SQL语句和EXPLAIN再复制一遍:

    SELECT you.nick_name,you.mobile,ycu.createtime,ycu.id,ycu.ym_userid, ycu.`status`,cir.coupon_name,cir.use_price,if(ycu.status = '1',ycul.createtime,'') as usedtime,cir.coupon_type as couponType, cir.price,cir.province,ycu.end_time 
    from ym_coupon_user ycu 
    
    LEFT JOIN ym_org_user you on ycu.ym_userid = you.id 
    
    LEFT JOIN coupon_issue_record cir on ycu.coupon_issue_record_id = cir.id 
    
    LEFT JOIN ym_coupon_used_log ycul on ycu.id = ycul.ym_coupon_user_id 
    
    where 1=1 and you.platform_code ='lngpt' 
    
    order by ycu.createtime desc 
    
    limit 10
     

      首先,当ycul表关联字段没加索引时,表ycu和表ycul都没有索引,虽然order by ycu.createtime,但ycu和ycul数据量差别很大,所以小表ycul被优化器选为驱动表。

      而此时order by ycu.createtime,即排序字段在非驱动表上,迫使MySQL使用了临时表,结果可想而知。

      当给ycul的ym_coupon_user_id加上索引,则优化器选择了ycu为主表,order by字段在主表,就没有临时表了。

     问题2. 什么时候会使用 join buffer

      …………待续

     问题3. 何时出现 Using filesort

      当Query中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序”

      

    stay hungry stay foolish!
  • 相关阅读:
    python xml dom
    python ::-1
    SigmoidCrossEntropyLoss
    pyplot
    注意mysql connector的版本
    caffe学习资料
    mysql中添加中文存储和显示功能
    centos7.3 安装cuda8.0的 坑
    Tree Widget -- 基本方法
    QLabel的使用
  • 原文地址:https://www.cnblogs.com/shog808/p/15091072.html
Copyright © 2020-2023  润新知