问题描述:今早一大早过来,运营的同事反馈系统比较卡,查了日志出现了很多dubbo服务超时的问题。找了运维的同事看了下,是数据库负载很高,大约是平时的10倍,其他系统因此也产生较多的服务调用超时的问题。

查找问题:根据cat的线上问题显示,查找到了是某一个DAO方法查询的时候出现慢查询,超出dubbo设置的超时时间,然后找运维的同事看了下线上慢查询,排名第一的就是这个DAO的SQL查询语句:

select qh.*, qi.status inquiryStatus, qi.inquiryId inquiryId, qi.failTime inquiryFailTime from qp_helpmefind qh left join qp_inquiry qi on(qh.helpMeFindId = qi.helpMeFindId) where 1=1 and qh.status != -1 order by inquiryId desc limit 0,12

分析问题:首先第一是登陆线上数据,然后 explain 下SQL语句,查看是否是索引没有加上或者不生效,结果如图: tupina 不是索引问题,有产生临时表以及文件排序,再去看执行的时间分布 tupina2

分析得SQL执行过程是:先扫描qp_helpmefind,然后再与qp_inquiry 做匹配,再把结果放到一张临时表,然后进行排序,慢查询主要的时间都是耗在将数据复制到临时表的过程,占了72%;最后的排序,占了总时间的12%。

解决问题: 将order by inquiryId desc 改为 order by qh.helpMeFindId desc, 即:

select qh.*, qi.status inquiryStatus, qi.inquiryId inquiryId, qi.failTime inquiryFailTime from qp_helpmefind qh left join qp_inquiry qi on(qh.helpMeFindId = qi.helpMeFindId) where 1=1 and qh.status != -1 order by qh.helpMeFindId desc limit 0,12

执行时间是0.02S,之前的是4S左右,explain 的结果如是: tupina

没有用到临时表 以及文件排序(left join使用主表的helpMeFindId进行排序,会用到索引进行排序),同时只扫描十几条数据,之前的是16W+。

解释:采用order by qh.helpMeFindId desc,从业务上讲,根据inquiryId来排序 和 根据 helpMeFindId 来排序,在页面展示上会有一定的排序上的区别,但影响比较小,可能导致的最糟糕情况会有部分 帮我找单 会放在相对靠后的几页,但不影响客服操作,相比线上多个系统受到此影响而言,可以接受,于是决定采用这种方式进行处理临时线上数据库负载超高的问题。