MYSQL调优之FileSort

参考https://blog.csdn.net/lijingkuan/article/details/50479679

最近在学习Explain分析SQL语句时,便好奇Extra列出现的UsingFileSort。

  • 然后大家都得知Using filesort是Mysql里一种速度比较慢的外部排序,如果能避免是最好的了,很多时候,我们可以通过优化索引来尽量避免出现Usingfilesort,从而提高速度。

  • 注:FileSort 并不是说通过磁盘文件进行排序,而只是告诉我们进行了一个排序操作——快速排序

一.在explain的时候为什么会出现using filesort

  • 答:这是因为在使用order by关键字的时候,如果待排序的内容不能由所使用的索引直接完成排序的话,那么mysql有可能就要进行文件排序。

  • 附: filesort是通过相应的排序算法,将取得的数据在内存中进行排序:。

二、这个FileSort执行过程是在哪进行的?

  • 答:Mysql一般是通过内存进行排序的,所使用的内存区域也就是我们通过sort_buffer_size 系统变量所设置的排序区。不过,要是超过了配置中的限制,应该会生成临时表。

注:这个排序区是每个Thread 独享的,所以说可能在同一时刻在MySQL 中可能存在多个 sort buffer 内存区域。

三.FileSort 的实现算法实际上是有两种

在这里插入图片描述
双路排序:是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行指针信息,然后在sort buffer 中进行排序。
单路排序:是一次性取出满足条件行的所有字段,然后在sort buffer中进行排序。

在MySQL4.1版本之前只有第一种排序算法双路排序,第二种算法是从MySQL4.1开始的改进算法,主要目的是为了减少第一次算法中需要两次访问表数据的 IO 操作,将两次变成了一次,但相应也会耗用更多的sortbuffer 空间。当然,MySQL4.1开始的以后所有版本同时也支持第一种算法。

MySQL主要通过比较我们所设定的系统参数max_length_for_sort_data的大小和Query 语句所取出的字段类型大小总和来判定需要使用哪一种排序算法。如果 max_length_for_sort_data更大,则使用第二种优化后的算法,反之使用第一种算法。所以如果希望 ORDER BY 操作的效率尽可能的高,一定要注意max_length_for_sort_data 参数的设置。如果filesort过程中,由于排序缓存的大小不够大,那么就可能会导致;临时表的使用。

max_length_for_sort_data的默认值是1024。


mysql在使用双路排序的时候,需要根据排好序的key,第二次去读取真正要返回的数据的。这样就会用到read_rnd_buffer_size这个参数定义的缓冲区。将读取的数据放到这个缓冲区中。

随机读取数据缓冲区使用内存(read_rnd_buffer_size):和顺序读取相对应,当 MySQL 进行非顺序读取(随机读取)数据块的时候,会利用这个缓冲区暂存读取的数据。如根据索引信息读取表数据,根据排序后的结果集与表进行Join等等。总的来说,就是当数据块的读取需要满足一定的顺序的情况下,MySQL 就需要产生随机读取,进而使用到 read_rnd_buffer_size 参数所设置的内存缓冲区。
参数:read_rnd_buffer_size,默认8MB。

顺便说下顺序读取缓冲read_buffer_size
顺序读取数据缓冲区使用内存(read_buffer_size):这部分内存主要用于当需要顺序读取数据的时候,如无法使用索引的情况下的全表扫描,全索引扫描等。在这种时候,MySQL 按照数据的存储顺序依次读取数据块,每次读取的数据块首先会暂存在read_buffer_size中,当buffer 空间被写满或者全部数据读取结束后,再将buffer中的数据返回给上层调用者,以提高效率。
参数:read_buffer_size,默认2MB

总结

1.当Where 条件和 order by 子句作用在不同的列上,建立联合索引可以避免Using filesort的产生,也可采用索引覆盖的方法进行解决

2.针对当前的例子实际上删除掉type列和id列上的单独索引,只保留联合索引也是可以达到相同效果的

3.通过比较时间发现去掉了Using filesort情况,耗时少了一点点,实际操作中是不稳定的,但是平均时间可能会有一点提升

猜你喜欢

转载自blog.csdn.net/weixin_42754971/article/details/113563042