当前位置: 首页 > 科技观察

MySQL是如何排序的?如何使用性能更快!

时间:2023-03-12 13:50:20 科技观察

经常听到这样的话,一个程序员在后台执行一条Sql语句,然后把在线服务给拖垮了。有人认为Sql的执行性能是DBA的事,但是随着互联网的发展,对开发的要求越来越高,尤其是一些小团队,恨不得人人都是全栈工程师。今天说说Mysql中的排序,OrderBy。我们在执行Mysql的Explain语句的时候,经常会看到这样的Usingfilesort。那么,Mysql的排序是在内存中还是在磁盘中进行的呢?如果我们是Mysql的设计者,我们会怎么做?首先,在内存中排序的速度肯定比在磁盘中快很多。但是,内存资源毕竟是有限的。如果我们扫描足够多的行,此时数据的大小可能会超过内存,在内存中排序是非常困难的。这个时候我们只能用磁盘来排序。没错,Mysql也是这样设计的。mysql有个配置项sort_buffer_size。如果我们选择的数据量小于这个数,那么数据会在内存中排序,否则,Mysql会把数据拆分成很多临时文件,每个临时文件的大小都会小于sort_buffer_size。也就是说,如果sort_buffer_size越小,就会拆分出越多的临时文件,这也是为什么我们选择存储的机器内存要尽可能大的原因。Mysql对多个临时文件进行排序后,最后进行归并排序,对所有记录进行排序。我相信如果你说下面的话,如果你的数据库有大量的列,尽量不要使用Select*而只选择你需要的字段,尤其是在数据库排序的时候。如果我们的数据有大量的列和大量符合条件的行,这时候Mysql就不得不使用比较极端的排序算法来进行排序。对于每一行数据,只取主键id和排序字段。然后排序,最后,取满足条件的结果返回到表中去查询其他字段,再返回结果。与上面的原方案相比,这种Rowid排序方式需要一次回表,查询效率大大降低。那么,我们可以做些什么来优化排序呢?我们都知道Innodb的索引其实是一个多叉排序树,如果能在现有的排序树上得到结果岂不是很好?!所以,如果我们要查询要排序的字段都在已有的索引上,并且满足最左前缀原则,那么就可以省去一次回表,从而大大提高效率。那么,你判断你的Sql语句是否满足这个优化呢?如果你的语句中包含OrderBy,但是Explain的结果只是UseIndex,说明命中了索引覆盖。当然,并不是所有的查询都必须命中索引覆盖。前面我们提到,维护索引的成本是很高的,需要具体问题具体分析。