本文转载自微信公众号《飞翔的小牛肉》,作者小牛肉。转载本文请联系飞天小牛公众号。假设有这样一张用户表user:idint(11):主键usernamevarchar(16):用户名ageint(11):agecityvarchar(16):city假设有这样一个需求:查询城市是“Nanjing”,按用户名排序,返回前1000个人的姓名和年龄。众所周知,排序使用的关键字是orderby。写这样一条SQL语句并不难:selectcity,username,agefromuserwherecity='Nanjing'orderbyusernamelimit1000;这篇文章,我们将讲解,涉及orderby的语句是如何执行的,以及哪些参数会影响执行行为全字段排序避免全表扫描,我们在查询条件的city字段上建一个索引,然后用explain命令看这条语句的执行情况:我偷懒了,因为我真的没有插入一条数据(狗头救命)),所以你在上图中看到的rows中的explain分析的SQL影响的行数是1Extra该字段中的Usingfilesort表示需要排序,MySQL会为每个线程分配一块内存用于排序,称为sort_buffer。正常情况下,这条语句的执行流程如下:1)初始化sort_buffer,放入city、username、age三个字段;2)从满足city='Nanjing'的索引city中查找第一个主键id3)到主键id的索引树上查找对应的整行数据(返回表查询),然后取取出city、username、age这三个字段的值,存入sort_buffer4)从索引city中取出下一条记录的主键id5)重复步骤3、4,直到city的值不6)根据字段username对sort_buffer中的数据进行快速排序根据字段username进行快速排序这个动作可能在内存中完成,也可能需要使用外部排序,这取决于排序需要的内存和sort_buffer的大小由参数sort_buffer_size决定。如果要排序的数据量小于sort_buffer_size,则在内存中进行排序。但是,如果需要排序的数据量太大,内存无法存储,就需要使用磁盘上的临时文件来辅助排序。解释使用临时磁盘文件进行辅助排序的意义。外部排序常用的排序算法是多路归并排序算法。具体步骤如下:在主键id索引树上找到对应的整行数据后,取city,username,age三个字段的值存入sort_buffer,可以存多少.当sort_buffer即将满时,对sort_buffer中的数据进行排序。排序后,暂时将数据放在磁盘上的一个小文件中。然后清空sort_buffer(这种情况下会把一个大数据分成几个临时磁盘文件)继续返回主键id索引树取数据,重复上一步,直到所有满足条件的数据都取完.最后按顺序合并7)根据排序结果,取前1000行返回给客户端。可以看出,我们要查询的城市、用户名、年龄都参与了整个排序过程,所以,暂且把这个排序过程称为全域排序。整个语句的执行流程示意图如下:关于上面提到的使用临时磁盘文件进行辅助排序的过程,不知道大家有没有自然而然的想法:sort_buffer如果内存不能存,需要一个临时磁盘文件。磁盘文件越多,排序效率越低。那为什么要把city和username这些与排序无关的字段放到sort_buffer中呢?只存储排序相关的age字段,所以这样划分的磁盘文件数量相对较少~这就是rowid排序
