专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

MySQL 的order by 原理, order by 的工作流程, order by 的执行过程

以下面这张表为例,看一下 order by 的工作流程。

68_1.png

city 字段建有索引。

执行:

select city,name,age

from t where city=’杭州’

order by name limit 1000 ;

查找 city 为‘杭州’的记录,根据 name 排序。

排序流程

先看下 city 索引的示意图:

68_2.png

上面查询语句的执行流程:

1、 初始化 sort_buffer,确定放入 name、city、age 这3个字段。
2、 从索引 city 中找到第一个满足 city=’杭州’ 的主键ID(ID_x)。
3、 到主键索引中找到 ID_x,取出整行,取 name、city、age 3个字段的值,存入 sort_buffer。
4、 从索引 city 取下一个记录的主键ID。
5、 重复3、4,直到 city 值不满足条件。
6、 对 sort_buffer 中的数据按照 name 做快速排序。
7、 把排序结果中的前1000行返回给客户端。

这个排序过程叫做全字段排序,因为需要返回的字段都放入了 sort_buffer 参与排序过程。

68_3.png

排序可能是在内存中完成,也可能需要外部排序,这取决于排序所需要的内存和 sort_buffer_size 参数值。

sort_buffer_size 是为排序而开辟的内存,如果排序的数据量小于其值,排序就在内存中完成,否则会利用磁盘临时文件来辅助排序。

上面的查询中只返回3个字段,不会太长,可以一起都放在 sort_buffer 中,但如果排序的单行长度太大,MySQL会怎么做?

假设 name、city、age 3个字段定义的总长度为36,而 max_length_for_sort_data = 16,就是单行的长度超了,MySQL认为单行太大,需要换一个算法。

此时,放入 sort_buffer 的字段就会只有要排序的字段 name,和主键 id,那么排序的结果中就少了 city 和 age,需要回表了。

排序流程变为:

1、 初始化 sort_buffer,确定放入2个字段,name 和 id。
2、 从索引 city 中找到第一个满足 city=’杭州’ 的主键ID(ID_x)。
3、 到主键索引中取出整行,把 name、id 这2个字段放入 sort_buffer。
4、 从索引 city 取下一个记录的主键ID。
5、 重复3、4,直到city值不满足条件。
6、 对 sort_buffer 中的数据按照 name 做快速排序。
7、 取排序结果中的前1000行,并按照 id 的值到原表中取出 name、city、age 3个字段的值返回给客户端。

这种排序成为rowid排序

68_4.png

如果内存够大,优先选择全字段排序,把需要的字段都放到 sort_buffer中,这样排序后就会直接从内存里返回查询结果了,不用回到原表取数据。

排序优化

建立一个 city、name 的联合索引,使查询 city='杭州' 的结果就是 name 有序的,就不用排序了。

68_5.png

查询过程变为:

1、 从索引(city,name)找到第一个满足 city=’杭州’ 的主键ID。
2、 到主键索引中取出整行,取 name、city、age 3个字段的值,作为结果集的一部分直接返回。
3、 从索引(city,name)取下一个主键ID。
4、 重复2、3,直到查到1000条,或者不满足条件时结束。

其实,这个查询还可以进一步优化,就是利用覆盖索引

使用联合索引(city,name)后已经不需要排序过程了,但因为没有 age 字段,所以还需要回表获取。

如果建立一个联合索引(city,name,age),不仅不用排序了,也不用回表取数据了,因为索引中已经包含了查询所需要的字段。

查询过程变为:

1、 从索引(city,name,age)找到第一个满足 city=’杭州’ 的记录,取出这3个字段,作为结果集的一部分直接返回。
2、 从索引取下一个记录,返回。
3、 重复2,直到查到1000条,或者条件不满足时结束。

小结

上面介绍了排序的工作流程,包括:

1、 全字段排序
2、 rowid 排序

并进一步思考如何对排序进行优化:

1、 利用索引使查询结果本身就是有序的。
2、 如果条件允许,使用覆盖索引,直接返回结果。

内容整理自丁奇的《MySQL实战45讲》

文章永久链接:https://tech.souyunku.com/12276

未经允许不得转载:搜云库技术团队 » MySQL 的order by 原理, order by 的工作流程, order by 的执行过程

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们