的简单介绍。对于面向业务(MySQL)的DBA或业务开发人员来说,按排序排序是一种常见的业务功能。将结果按照指定的字段进行排序,以满足前端展示的要求。需要。然而,排序操作也是慢查询排行榜的常客。这篇文章会从原理和实际案例优化,orderbyusagelimits等几个方面逐步了解orderbysorting。两个原理在理解orderbysorting原理之前,我强烈amway了两篇关于排序算法的文章《归并排序的实现》《经典排序算法》.MySQL支持正则排序和优化两种排序算法,而在MySQL5.6中,对orderbylimitM、N进行了特殊优化,这里列为第三种。2.1常规排序a从表t1中获取满足WHERE条件的记录b对于每条记录,取出该记录的主键+排序键(id,col2)放入排序缓冲区c如果排序缓冲区可以存储所有的(id,col2)满足条件的)是,则排序;否则,当排序缓冲区已满时,排序并固化到一个临时文件中。(排序算法使用快速排序算法)d如果排序时产生了临时文件,需要使用归并排序算法保证临时文件中的记录是有序的扫描排序好的(id,col2)对,并使用id检索SELECT需要返回的列(col1,col2,col3),将得到的结果集返回给用户。从上面的过程来看,是否使用文件排序主要看sortbuffer能否容纳需要排序的(id,col2)对。此缓冲区的大小由sort_buffer_size参数控制。另外,一次排序需要两次IO,一次是检索(id,col2),二是检索(col1,col2,col3)。由于返回的结果集是按col2排序的,所以id是乱序的。获取id(col1,col2,col3)时会产生大量随机IO。MySQL本身的二次优化,先将ids排序,放入buffer中,再进行钓鱼。这个buffer的大小是通过参数read_rnd_buffer_size来控制的,然后将record排序到fish中,以便将随机IO转化为顺序IO。2.2优化排序除了排序本身,传统的排序方法还需要额外的两个IO。与常规排序相比,优化后的排序方式减少了二次IO。主要区别在于它不是将(id,col2)放入排序缓冲区,而是放入(col1,col2,col3)。由于排序缓冲区中包含了查询所需的所有字段,因此排序完成后可以直接返回,无需检索数据。这种方法的代价是相同大小的排序缓冲区中可以存储的(col1,col2,col3)个数小于(id,col2)。如果排序缓冲区不够大,可能需要写入临时文件,导致额外的IO。当然,MySQL提供了参数max_length_for_sort_data,只有当排序后的元组小于max_length_for_sort_data时,才可以使用优化排序方式,否则只能使用常规排序方式。2.3优先队列排序为了得到最终的排序结果,不管怎样,我们都需要将所有满足条件的记录排序后再返回。那么相比于优化排序方式,是否还有优化空间呢?5.6版本在空间层面对OrderbylimitM,N语句进行了优化,增加了一种新的排序方式:优先队列,使用堆排序完成。堆排序算法的特点恰好可以解决限制M和N等排序问题,虽然仍然要求所有元素都参与排序,但只需要M+N个元组的排序缓冲空间。对于M和N较小的场景,基本上不会出现排序缓冲区不足而需要临时文件进行归并排序的问题。对于升序,使用大顶堆,最后堆中的元素构成最小的N个元素。对于降序,使用小顶堆,最后堆中的元素组成最大的N个元素。三优化通过以上原理的分析,我们知道排序的本质是通过一定的算法(消耗cpu操作、内存、临时文件IO)将结果集变成有序的结果集。如何优化呢?答案是在两个方面利用索引的有序性(MySQL的B+树索引默认是从小到大递增排序)来减少排序。最好的办法就是不直接排序。createtablet1(idintnotnullprimarykey,key_part1int(10)notnull,key_part2varchar(10)notnulldefault'',key_part3keyidx_kp1_kp2(key_part1,key_part2,key_part4),keyidx_kp3(id))engine=innodbdefaultcharset=utf8可以使用索引idx_kp1_kp2FROMt1ORDERBYkey,...;SELECT*FROMt1WHEREkey_part1=constantORDERBYkey_part2;SELECT*FROMt1ORDERBYkey_part1DESC,key_part2DESC;SELECT*FROMt1WHEREkey_part1=1ORDERBYkey_part1DESC,key_part2DESC;SELECT*FROMt1WHEREkey_part1>constantORDERBYkey_part1ASC;SELECT*FROMt1WHEREkey_part1
