我的编程空间,编程开发者的网络收藏夹
学习永远不晚

MySQL45讲之order工作原理 - flowers

短信预约 信息系统项目管理师 报名、考试、查分时间动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

MySQL45讲之order工作原理 - flowers

MySQL45讲之order工作原理 - flowers

本文介绍 order 的三种排序方式,全字段排序、rowid 排序和索引树排序,以及每种排序方式具体是如何工作的。

前言

本文介绍 order 的三种排序方式,全字段排序、rowid 排序和索引树排序,以及每种排序方式具体是如何工作的。

当使用 explain 查看执行计划时,如果 extra 中有 Using filesort,表示经过了排序。

MySQL 会在内存中分配一块内存专门用来排序,可以通过 sort_buffer_size 设置大小。如果需要排序的数据量小于 sort_buffer_size,排序在内存中进行,否则,需要采用 外部排序方法,即借助磁盘排序。

可以通过 OPTIMIZER_TRACE 的结果来查看是否使用了临时文件,


SET optimizer_trace="enabled=on"; 


SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`;

全字段排序

在 city 列已建立普通索引情况下,对于语句 select city,name,age from t where city="杭州" order by name limit 1000; 进行全字段排序流程是:

  1. 初始化 sort_buffer,确定放入 city,name,age 字段
  2. 遍历 city 索引树,找到第一个 city = "杭州" 的节点,拿到 id
  3. 根据 id 从主键索引树中拿到需要返回的字段值,放入 sort_buffer
  4. 循环执行 2,3 往后遍历,直到 city != "杭州",然后再执行后面流程
  5. 对 sort_buffer 中的数据按 name 排序
  6. 取出前 1000 行返回客户端

将要返回的字段全部放到 sort_buffer 进行排序,所以叫全字段排序。

这个算法有个缺点,如果要返回的字段很多,则一行数据的体积很大,这样很可能要用到外部排序,并且一个文件存下的行数有限,需要比较多的临时文件,临时文件一多,排序性能将十分低,所以这时 MySQL 会采用 rowid 排序算法。

rowid排序

当返回的字段很多时,MySQL 将采用 rowid 排序算法。那字段很多的标准是如何界定的呢?MySQL 有一个参数 max_length_for_sort_data,当字段类型的总字节数大于 max_length_for_sort_data 时将采用 rowid 算法。比如,select city,name,age from t where city="杭州" order by name limit 1000; 中 city 和 name 字符串长度都是 16,age 占 4 字节,即总共 36 字节。

在 city 列已建立普通索引情况下,对于语句 select city,name,age from t where city="杭州" order by name limit 1000; 进行 rowid 排序流程是:

  1. 初始化 sort_buffer,确定放入 name, id 字段
  2. 遍历 city 索引树,找到第一个 city = "杭州" 的节点,拿到 id
  3. 根据 id 从主键索引树中拿到 name,id 字段值,放入 sort_buffer
  4. 循环执行 2,3 往后遍历,直到 city != "杭州",然后再执行后面流程
  5. 对 sort_buffer 中的数据按 name 排序
  6. 取出前 1000 行,按照 id 回到原表中取到 city,name,age 值再返回客户端

从上面流程可见,rowid 排序算法在 sort_buffer 中只放入了排序字段和 id,尽可能避免了外部排序低效的问题,但排序之后,还需要回表重新取一遍返回值的数据。

索引树排序

你或许会问,那有没有可以不排序的算法?

有的,就是索引树排序,因为字段值在索引树上已经有序,所以可以直接遍历索引树取到 id,然后到主键索引树拿返回值返回,不需要再排序。

那能不能直接从索引树中就拿到返回的数据,不要再回表呢?

当然也是可以的,这就是索引覆盖的思想,比如 select city,name,age from t where city="杭州" order by name limit 1000; 语句,只要建立联合索引 (city, name, age),就可以避免回表操作。

提问

假设你的表里面已经有了 city_name(city, name) 这个联合索引,然后你要查杭州和苏州两个城市中所有的市民的姓名,并且按名字排序,显示前 100 条记录。如果 SQL 查询语句是这么写的 :

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `city` varchar(16) NOT NULL,
  `name` varchar(16) NOT NULL,
  `age` int(11) NOT NULL,
  `addr` varchar(128) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `city` (`city`)
) ENGINE=InnoDB;

select * from t where city in ("杭州","苏州") order by name limit 100;

那么,这个语句执行的时候会有排序过程吗,为什么?

回答:会,因为 city_name 索引只能保证 city 相同的情况下,name 有序。而此时查询两个城市,那么显然不能保证按 name 有序。

如果业务端代码由你来开发,需要实现一个在数据库端不需要排序的方案,你会怎么实现呢?

回答:可以建立联合索引 (name, city) 来避免排序。

进一步地,如果有分页需求,要显示第101页,也就是说语句最后要改成 “limit 10000,100”, 你的实现方法又会是什么呢?

回答:

没有比较好的优化方法。首先看业务是否可以砍掉这个排序的需求,让用户只能一页一页翻,这样用户基本也就只会看前几页,就不需要考虑这个大分页情况了。为了意义不大的功能优化,可能会得不偿失。

如果实在需要,就可以先建立联合索引 (name, city),再通过下面的 SQL 查询。

SELECT * FROM t WHERE id IN ( SELECT id FROM t WHERE city IN ("杭州","苏州") ORDER BY name LIMIT 10000,100 ) AS tmp;

内查询直接索引覆盖,遍历 10100 个节点,拿到末尾的 100 个 id,不需要回表。再在外查询中,根据 id 从表中拿到数据返回客户端。这样,可以避免回表取 10100 次数据,如果符合的数据够 10100 条的话。

参考

  • [1] “orderby”是怎么工作的

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

MySQL45讲之order工作原理 - flowers

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

MySQL45讲之order工作原理 - flowers

本文介绍 order 的三种排序方式,全字段排序、rowid 排序和索引树排序,以及每种排序方式具体是如何工作的。 前言本文介绍 order 的三种排序方式,全字段排序、rowid 排序和索引树排序,以及每种排序方式具体是如何工作的。当使用 explai
MySQL45讲之order工作原理 - flowers
2017-04-04

MySQL45讲之count操作 - flowers

本文介绍 MyISAM 和 InnoDB 如何执行 count 操作,如果是一个需要使用 count 进行大量计数的场景,应该如何设计实现,以及不同 count 操作的效率。 前言本文介绍 MyISAM 和 InnoDB 如何执行 count 操作,如果
MySQL45讲之count操作 - flowers
2021-05-25

UAV MOF工作原理之Agent注入机制原理

一、前言MOF(Moniter Framwork)作为UAV应用数据捕获框架,不但实现了对应用无侵入的数据捕获,而且在框架层面实现了功能的灵活控制,并且保证了良好的可扩展性,在UAV中具有举足轻重的地位。MOF Agent注入机制作为UAV
2023-06-04

spark之pipeline的工作原理是什么

Spark的Pipeline是一种用于将多个数据处理步骤串联起来形成一个完整的数据处理流程的机制。Pipeline的工作原理如下:数据输入:Pipeline首先接受输入数据,可以是来自文件、数据库、实时流等数据源。数据转换:Pipeline
spark之pipeline的工作原理是什么
2024-04-03

servlet之session工作原理简介_动力节点Java学院整理

要了解Session的底层工作原理。我们还是先看在一个会话过程中,同一个浏览器在访问多个web资源的情况好了,大致分为以下几个步骤:1,浏览器访问某个Servlet,这时如果服务器要从请求对象中获取Session对象(第一次获取也是创建),
2023-05-31

Node之Cookie-Session登录验证的工作原理是什么

这篇文章主要介绍“Node学习之聊聊Cookie-Session登录验证的工作原理”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Node学习之聊聊Cookie-Session登录验证的工作原理”文章
2023-07-04

java编程之AC自动机工作原理的示例分析

这篇文章将为大家详细讲解有关java编程之AC自动机工作原理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1.应用场景—多模字符串匹配我们现在考虑这样一个问题,在一个文本串text中,我们想找出
2023-05-30

Node学习之聊聊Cookie-Session登录验证的工作原理

实现登录验证的功能主要有Cookie&Session、JWT两种方式,这一节我们将先对 Cookie&Session的工作原理 做详细的介绍,在之后的文章中会陆续对JWT,以及如何使用Cookie&Session和JWT来完善前几节我们搭建的简易用户管理系统进行讲解。
2023-05-14

docker笔记31_1-容器之间通讯方式及Flannel工作原理

转自:https://blog.csdn.net/weixin_29115985/article/details/78963125 一. 容器之间通讯方式k8s里面容器是存在于pod里面的,所以容器之间通讯,一般分为三种类型:(1) pod
2023-06-04

编程热搜

目录