IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 读mysql45讲-order by排序 -> 正文阅读

[大数据]读mysql45讲-order by排序

假设有一张表,DDL如下:

CREATE TABLE `t_user_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL,
  `city_name` varchar(100) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5001 DEFAULT CHARSET=utf8

插入数据的存储过程:

CREATE DEFINER=`zhuruilin_dev`@`%` PROCEDURE `dev`.`test1`()
begin declare i int;
set
i = 1;

while(i <= 5000)do
insert into t_user_info(name,city_name,age) 
values(concat('机器人' , i , '号'),concat('模拟城市',i%2,'号'), i);
set
i = i + 1;
end while;
end

有一个高频请求查询是根据一个城市的所有人的名字,年龄,以及城市名,并且根据姓名排序,取前1000条。

explain select city_name,age,name
from t_user_info tui 
where tui.city_name  = '模拟城市0号'
order by name
limit 1000

没有给city_name添加索引前:

在这里插入图片描述

给city_name加了索引之后:

在这里插入图片描述

Extra这个字段中的“Using filesort”表示的就是需要排序,MySQL会给每个线程分配一块内存用于
排序,称为sort_buffer

执行sql的大概流程就是:

  • 初始化sort_buffer,讲name,age,city_name就是查询字段放进去
  • 找到第一个满足 city_name = ’模拟城市0号‘的索引项,
  • 根据找到的第一个满足条件的索引项的id,进行回表操作,取 name,age,city_name字段的值放入sort_buffer中;
  • 继续寻找满足条件的索引项,并且重复上面的操作,直到不满足查询条件
  • 讲sort_buffer中的数据根据name字段进行排序
  • 取前1000条记录返回

按照name字段排序这个步骤可能是在内存中完成,也可能需要使用外部排序,也就是借用磁盘空间进行排序,这个取决于排序所需要的内存和参数sort_buffer_size。参数sort_buffer_size就是MYSQL预先设置好排序可以使用的内存大小。如果排序的数据量小于sort_buffer_size的大小,那就在内存中完成;否则就利用磁盘临时文件辅助排序。

当需要使用外部排序的时候(外部排序通常使用归并排序算法),MYSQL将整个数据分成好几份,每一份排完序之后就单独放在一个临时文件中,然后统一把所有的单独的排好序的临时文件再合并成一个有序的文件。

使用rowid排序

上面的算法中,只在根据id查询name,age,city_name的时候进行了回表的操作;剩下的都是在sort_buffer和临时文件中进行的,如果需要回表查询的字段很多的话,那sort_buffer中就会被占用很大空间,但实际的行数却很少,就需要分成很多个临时文件,排序的性能就有下降。

max_length_for_sort_data,是MySQL中专门控制用于排序的行数据的长度的一个参数。它的意 思是,如果单行的长度超过这个值,MySQL就认为单行太大,要换一个算法。

大概的流程如下:

  • 初始化sort_buffer,将需要排序的字段和主键id放入
  • 从索引树上找到第一个满足city_name='模拟城市0号’的索引项
  • 根据索引项中的id回表查询到name,id;放入到sort_buffer中;
  • 继续寻找满足条件的数据,重复上面的操作
  • 直到找到不满足条件的数据,
  • 对sort_buffer中数据根据name字段进行排序
  • 取前1000个数据的id,然后回表去查询name,city_name,age,返回

rowid排序过程和上面全字段排序过程的区别就是多了一个回表查询name,city_name,age的操作,在rowid的第三个步骤中,只是将name,id放入了sort_buffer中,比全字段排序过程中的第三个步骤放入的字段少了一些;这样的话sort_buffer就可以放入更多的行数,避免了使用很多临时文件的情况。

其实,并不是所有的order by语句,都需要排序操作的。从上面分析的执行过程,我们可以看 到,MySQL之所以需要生成临时表,并且在临时表上做排序操作,其原因是原来的数据都是无序的。如果根据city_name这个有索引的字段找到name都是排序好的,那是不是就不需要再排序了?

创建一个city_name和name的联合索引,再次查询sql:

在这里插入图片描述

Extra字段中没有Using filesort了,也就是不需要排序了。

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2022-03-04 15:39:43  更:2022-03-04 15:43:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:34:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码