工作中遇到的bug(记录一下)

 与其说是bug,倒不如说是自己的失误。

背景:php代码重构为go语言beego项目,重构完后,对部分接口进行压测,发现某个接口qps一直上不去,响应时间非常高。经过排查发现是数据库查询花了很多时间。

表是一张两千万张数据的表。有建立索引

sql如下:

SELECT
user_id,count(1) as count
FROM
star_fans
WHERE flag=1 and user_id in (
2165,286,2471,3052892,13582,1351
)
GROUP BY user_id

通过explain sql 分析sql 发现Select_type 为index 

根据这个命令的相关字段详解发现:

表示MySQL在表中找到所需行的方式,又称“访问类型”。

常用的类型有: ALL, index,  range, ref, eq_ref, const, system, NULL(从左到右,性能从差到好)

Select_type 说明查询中使用到的索引类型,如果没有用有用到索引则为all

ALL:Full Table Scan, MySQL将遍历全表以找到匹配的行

index: Full Index Scan,index与ALL区别为index类型只遍历索引树

range:只检索给定范围的行,使用一个索引来选择行

ref: 表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值

eq_ref: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件

const、system: 当MySQL对查询某部分进行优化,并转换为一个常量时,使用这些类型访问。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system

NULL: MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。

其中row居然是完整的2000w条数据,意味着等于全表扫描了。

所以非常疑惑,况且对索引的理解不是很深,看了表结构,发现索引建立的也没问题。况且php中也是使用同样的sql,它的接口却访问的很快。

后面几经排查,发现是由于sql中数据类型不对导致的,string类型没有加引号,php为弱类型语言,可能orm框架中有对其进行优化。

果不其然,sql改为:SELECT
user_id,count(1) as count
FROM
star_fans
WHERE flag=1 and user_id in (
'2165','286','2471','3052892','13582','1351'
)
GROUP BY user_id

再通过explain sql发现 select_type变成了range ,同时rows变成几万条而不是两千万条

 总结:在写业务代码时或者重构时,要注意不同语言的差异,以免踩坑,虽然不加引号也能查出来,但是效率却是千差万别,足以说明压测的必要性,以及写代码时的严谨性,可以运行是一回事,写出优秀的代码更是不容易。

 

上一篇:记,第一次跑实验失败,第一次回滚本地虚拟机环境


下一篇:regreport bug