当使用order by对查询结果进行排序时,MySQL会给每个线程分配一块儿内存sort_buffer用于排序,在使用索引的情况下,整个的排序过程如下所述:
1. 初始化sort_buffer,确定放入结果中所需的字段;
2. 从索引中找到第一个满足条件主键id;
3. 到主键id索引取出整行,取所需字段的值,存入sort_buffer中;
4. 从索引中取下一个记录的主键id;
5. 重复步骤3、4直到索引中的值不满足查询条件为止;
6. 对sort_buffer中的数据按照order by
的字段做快速排序;
7. 根据limit
语句按照排序结果取前n行返回给客户端
其中第六步的排序,如果内存大小不够则可能使用外部文件进行排序,缓存大小取决于sort_buffer_size
,如果使用外部文件,则采用类似于归并排序的方式
当结果中需要的字段过多时 ,每行记录比较大,可能会发生sort_buffer只能放下很少的记录的情况,这时,需要的就是rowid排序。max_length_for_sort_data
用于控制缓存中每行能放下的数据大小,如果不能将所需字段都放进去,则会选择order by
中需要的字段放进去,其余的字段通过回表的方式,将第7步改为:遍历排序结果,取前n行,并按照id的值回到原表中取出所需字段返回给客户端。也是由于这个回表过程的存在,所以MySQL会优先选择第一种方法,尽量避免rowid方式,此外还可以通过覆盖索引的方式再次减少回表过程。
MySQL实战45讲