- MySQL会给每个线程分配一块内存用于排序,称为sort_buffer
- 执行流程,如下:
- 初始化sort_buffer,确定放入select的字段
- 找到满足条件的行取出select的字段存入sort_buffer中
- 一直查找到不满足条件的为止
- 对sort_buffer中的数据按照排序的字段做排序
- sort_buffer_size可以设置sort_buffer的大小。 如果要排序的数据量小于 sort_buffer_size,排序就在内存中完成。 但如果排序数据量太大,内存放不下,则不得不利用磁盘临时文件辅助排序。
- max_length_for_sort_data,是 MySQL 中专门控制用于排序的行数据的长度的一个参数。它的意思是,如果单行的长度超过这个值,MySQL 就认为单行太大,要换一个算法
- 执行流程,如下:
- 初始化sort_buffer,确定放入id和要排序的字段
- 找到满足条件的行取出这两个字段存入sort_buffer中
- 一直查找到不满足条件的为止
- 对sort_buffer中的数据按照排序的字段做排序
- 遍历排序结果,并按照id的值回表取出select的字段
- 如果MySQL认为内存足够大就会使用全字段排序,否则会使用rowid排序。 对于 InnoDB 表来说,rowid 排序会要求回表多造成磁盘大量随机读,因此不会被优先选择
- 联合索引能直接确定顺序,查询过程不需要临时表,也不需要排序了
- 覆盖索引是指,索引上的信息足够满足查询请求,不需要再回到主键索引上去取数据
- 执行计划中如果出现
using filesort
就会走如上的执行流程,对于Mysql来说,数据量小则在内存中进行排序,数据量大则需要在磁盘中排序,这个过程统一都叫做filesort
。- 首先根据索引找到对应的数据,然后把数据放入排序缓冲区中
- 如果要排序的数据实际大小没有超过缓冲区大小,就会使用内存排序,如快速排序,然后取出符合条件的数据返回
- 如果超过了缓冲区大小,就需要使用外部排序,算法一般使用多路归并排序,首先对数据分块,然后对每块数据进行排序,排序结果保存在磁盘中,最后将排序结果合
- 缓冲区大小、排序字段的数据长度、查询数据条数等都会影响查询性能
- 优化的方式就是尽量让查询出来的数据已经是排好序的,也就是合理使用联合索引以及覆盖索引