16 “Order by”是怎么工作的
全字段排序
MySQL会给每个线程分配一块内存用于排序,称为sort_buffer。
通常情况下,语句执行流程如下
1.初始化sort_buffer,确定放入name,city,age三个字段;
2.从索引City找到第一个满足city=”杭州”条件的主键id,也就是ID_X
3.到主键id索引取出整行,取name,city,age三个字段的值,存入sort——buffer中
4.从索引city取下一个记录的主键id
5.重复3.4直到city的值不满足查询条件为止,对应的主键id也就是ID_Y
6.对sort_buffer中的数据按照字段name做快速排序
7.按照排序结果取前1000行返回给客户端
按name排序可能在内存中完成,也可能使用外部排序,取决于排序所需内存和参数sort_buffer_size
sort_buffer_size,就是为排序开辟的内存(sort_buffer)的大小。如果排序数据量小于sort_buffer_size,就是在内存中完成。
内存放不下,就需要外部排序,外部排序一般使用归并排序算法。
Mysql把需要排序的数据分成12份,每一份单独排序后存在这些零时文件中,然后把这12个有序文件合并成一个有序的大文件
Rowid排序
如果单行的长度超过max_length_for_sort_data这个值,就会认为单行太大,需要换一个算法。
Rowid排序多访问一次表t的主键索引
全字段排序vs rowid排序
Mysql实在担心排序内存太小,会影响排序效率才会采用rowid算法,这样排序过程一次可以排更多行,但是需要回到原表取数据。
认为内存足够大,会优先选择全字段排序,把需要的字段都放到sort_buffer中,这样排序后就会直接从内存里面返回查询结果,不用再到原表取数据。
如果内存够,就要多利用内存,尽量减少磁盘访问。
如果从索引上取下来的行,天然就是按照递增排序的,就不用再排序
如果使用覆盖索引,那么索引上的信息足够满足查询请求,就不需要再回到主键索引上取数据。