当前位置: 首页 > 后端技术 > PHP

[业务学习]MySQLorderbylimit索引错误的讨论

时间:2023-03-29 18:05:55 PHP

Grape描述今天运行脚本的时候,发现几个慢查询。就记录在这里吧。首先,我的sql看起来像这样:从`xxx`强制索引(idx_d_t)中选择`id`,其中`date`='2019-09-11'AND`time_flag`<'20190911220000'orderbyidasc;索引在下面它看起来像这样:KEY`inx_t_d`(`date`,`time_flag`);按照我之前的理解,这个SQL可以使用这个索引,但是他没有,他选择了主键索引。分析看到这是一个慢查询,于是开始解释,结果如下:我肯定不满意这个结果,为什么要用主键索引,于是开始了百度谷歌之旅。一开始,我找到了一个我认为比较正确的方法。找了某度上的一篇文章说如果orderby之前有范围搜索,则使用orderby之后的索引,否则使用orderby之前的索引。我试了一下,哎,不错,把范围查询改成等价的查询,我的索引没了,但是看了一眼行数,一脸懵逼。为什么有这么多行?这不是我想要的。然后通过profiling(可以百度)查看时间,发现创建排序索引占用了90%的时间。这个时候我就敏锐的意识到这个排序有问题。不,继续检查!继续查,去找某哥,哎,不说了,某哥的大法还是不错的,终于找到了大佬的分析,具体是什么原因呢?第一次强制我的联合索引看情况:看到上图你会发现Usingfilesort这个东西有区别。这是什么?简单的说,filesort就是将获取到的数据在内存中通过相应的排序算法进行排序。俗话说,有对比才会有伤害。如果你抓住了敌人的辫子,你就离胜利不远了。让我们继续观望。Fliesort有两种排序方式:双向排序:首先根据相应的条件,取出对应的排序字段和可以直接定位行数据的行指针信息,然后在排序缓冲区中进行排序。单向排序:是一次性取出满足条件的行的所有字段,然后在排序缓冲区中排序。这两个什么时候用?MySQL主要通过比较设置的系统参数max_length_for_sort_data的大小与Query语句提取的字段类型的大小之和来决定需要使用哪种排序算法。如果max_length_for_sort_data较大,则使用第二种优化算法,否则使用第一种算法。显然,MySQL应该尽可能选择使用第二种单向算法进行排序。这样可以减少大量的随机IO操作,大大提高排序工作的效率。上面分析的排序时间长可能与此有关。继续查看数据分析。问题的关键在于为什么会出现filesort。结论在执行语句时,由于数据量较大,MySQL优化器认为使用联合索引不好,默认选择第一个较慢的执行计划。原因是主键索引不需要内存排序,候选idx_d_t被淘汰。优化器认为主键索引比联合索引好,所以才会出现这种情况,那么我们该怎么办,这里我只列出我的解决方案,他认为主键更好,那我们就给他一个更好的一,我们将索引idx_d_t从date,time_flag改为id,date,time_flag,问题解决。如图:最后总结一下,优化器会尽量避免file_sort,这可能会导致一些问题。以上分析如有错误请指出!感激的。参考文章:MySQLorderbylimit错误索引