导读:在日常的MySQL的SQL语句优化工作中,总会遇到了各种各样的问题。今天就是遇到了一个比较诡异的问题,在这里记录下来方便自己的记忆。
MySQL版本信息: MySQL 5.6.38
SQL语句(其中的关键字信息已经做脱敏处理):
SELECT id, name, headurl, intro, gender, location, job, birthday, source,created_at FROM user WHERE name LIKE '%name%' ORDER BY created_at DESC LIMIT 0, 100;
2. 表user的表结构:
3. SQL的执行计划和profile信息以及执行耗时:
4.优化思路:在执行计划中可以看得到SQL语句由于是模糊查询所以并没有使用索引,并且在执行SQL之后可以明显的看出在创建排序索引上面耗费了99%以上的时间,我们在看整个的SQL语句,只有在字段created_at上面有做排序操作,所以按照优化思路那么我们就需要在created_at这个字段上面创建索引。创建索引之后的表结构:红框就是添加的索引信息。
5.修改之后的SQL的执行计划和profile以及耗时信息:
在上面的执行计划进行比对我们可以很明显的看出来,返回的数据由450w减少到了100行,数据量大大的减少了;但是在执行SQL之后发现耗时居然更长了使用了6s多,并且分析profile的时候发现在sending data耗时花费了6.6s的样子,在这里解释一下 sending data耗时指的的是从引擎层发送数据到server层或者是client层。
发现这种情况我感到很吃惊,我并不知道发生了什么事情导致这种结果。在多方查询无果之后我之后请教我的一个师兄,经过我详细的描述和实验,他告诉我:主要是由于在where条件过滤和排序的时候走索引没有查询到任何的结果导致mysql获取查询所有的索引然后在去回表进行全局扫描;在没有添加的索引的情况下,SQL直接就回回表不会进行全部的索引扫描。
为了验证这个结果,我更改了where条件,在没有添加created_at这个字段索引的情况下进行对比情况:
没有添加索引的耗时:
100 rows in set (2.53 sec)
添加索引的耗时:
100 rows in set (0.16 sec)
可以很明显的看到添加索引之后 速度提高了一大堆,并且这个是有查询结果的。