前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL order by 是怎么工作的?

MySQL order by 是怎么工作的?

作者头像
dys
发布2019-05-13 16:17:23
1.7K0
发布2019-05-13 16:17:23
举报
文章被收录于专栏:性能与架构性能与架构

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

city 字段建有索引。

执行:

select city,name,age

from t where city='杭州'

order by name limit 1000 ;

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

排序流程

先看下 city 索引的示意图:

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

  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 参与排序过程。

排序可能是在内存中完成,也可能需要外部排序,这取决于排序所需要的内存和 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排序

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

排序优化

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

查询过程变为:

  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讲》

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JAVA高性能架构 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 排序流程
  • 排序优化
  • 小结
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档