有一个mysql查询场景:
- 单表数据量不会太大,总数量在几万条近十万
- 有一个status字段,取值可能为0、1、2,初始为0,后续会变为1、2
- 绝大多数数据的status为2,少量为0
- 查询场景是会不断的查出status为0的数据来进行处理
之前开发想着总数据量就这么点,status为0的数据也不多,根据status查询的时候性能不至于太低,就没建索引硬查了。
然鹅,在测试环境跑了一段时间后,mysql告警了,cpu爆炸了。上日志平台查看,找到了一些慢查询,就是简简单单的,上面的select。
写代码用的是orm框架sequelize,就是一个简单的findOne。
对应的慢查询:
一个select语句耗时3s,而且整张表里边其实一条数据status=0的数据都没有,全部是status=2的数据。这里把status换成2之后,耗时立马变成了瞬间完成。
分析一下执行过程:
发现进行了全表扫描。
同样是全表扫描,status=2时,因为全部都是满足条件的数据,扫到第一条就返回了,所以速度很快。
status=0时,则会真的扫完全表都找不到记录,返回empty set。
这里仔细分析了一下,数据量也不大全表扫描也不至于3秒,后来挨个看字段,想起了在status=2时,result里边会被塞入大量的结果,其本身是一个mediumtext字段。
试验一下,只select id,全表扫描的速度也立马起来了!耗时在十来毫秒。而像上面一样加入result字段后,整个查询就变成了慢查询。
这里加个索引可以更快,给status加上索引
经验:
- 当表里有大尺寸数据的字段存在时,要格外关注查询性能
- 项目测试阶段要对mysql表索引是否合理,进行排查
本文链接:https://www.zoucz.com/blog/2020/07/20/01427d60-ca5f-11ea-90b5-eb40e9720ed0/