mysql 排序底层原理解析

前言

本章详细讲下排序,排序在我们业务开发非常常见,有对时间进行排序,又对城市进行排序的。不合适的排序,将对系统是灾难性的,这个不是危言耸听。可能有些人会想,对于排序mysql 是怎么实现的,它的底层原理是怎么样的,如果我加上分页,排序是不是就会快一些。关于这些问题,本章详细讲解。

有人经常问我,mysql 优化的规则,总是不假思索的说ESR,E 是 equal ,S是sort 。可见排序有多么重要,为了讲解方便,我先画个思维导图。

上图标的1,2 是mysql 配置文件可以配置的。可以通过 show variables like 'max_length_for_sort_data'; 可以具体的配置。从图上我们可以看到mysql 排序分为全字段排序,和 rowid 。这是两大类,里面又分为内存排序,文件排序,我将从这2大类4小类讲解。

全字段排序

由上图可以看出 Extra = Using filesort 就表示了排序,但此时还不能判断是文件排序还是内存排序

可以根据下面介绍的方法,来确定一个排序语句是否使用了临时文件

/* 打开optimizer_trace,只对本线程有效 */
SET optimizer_trace='enabled=on'; 
​
/* @a保存Innodb_rows_read的初始值 */
select VARIABLE_VALUE into @a from  performance_schema.session_status where variable_name = 'Innodb_rows_read';
​
/* 执行语句 */
select city, name,age from t where city='杭州' order by name limit 1000; 
​
/* 查看 OPTIMIZER_TRACE 输出 */
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G
​
/* @b保存Innodb_rows_read的当前值 */
select VARIABLE_VALUE into @b from performance_schema.session_status where variable_name = 'Innodb_rows_read';
​
/* 计算Innodb_rows_read差值 */
select @b-@a;
​
### 

Number_of_tmp_files>0 就表示文件排序,没有就表示是内存排序。sort_buffer_size 越小,那么 Number_of_tmp_files 就会越大,文件排序用的是归并排序,也就是把数据分给多个文件,每个文件排序后,最终合并一个文件。

上面sort_mode 可以看到,这是一个全字段排序,什么是全字段排序,就拿上面这个sql 语句来说,city ,name,age 都在文件里,对name 进行排序

这个排序的内部是这么实现的:

  1. 初始化 sort_buffer,确定放入 name、city、age 这三个字段;

  2. 从索引 city 找到第一个满足 city='杭州’ 条件的主键 id

  3. 到主键 id 索引取出整行,取 name、city、age 三个字段的值,存入 sort_buffer 中;

  4. 从索引 city 取下一个满足 city='杭州’ 的主键 id;

  5. 重复步骤 3、4 直到 city 的值不满足查询条件为止

  6. 对 sort_buffer 中的数据按照字段 name 做快速排序;

  7. 按照排序结果取前 1000 行返回给客户端。

由此我们发现,排序会对表的所有的记录进行排序,然后在取出1000条

rowid

如果 排序数据的长度超过了 max_length_for_sort_data 就是 rowid排序。排序数据的长度就是指拿上面这个例子说 name、city、age 这三个字段大于 max_length_for_sort_data 就是rowid 排序。为什么会这样的呢,mysql 会尽量用内存排序,字段越长,占用空间越大,未了提高排序效率,就会用rowid 排序。

rowid排序的步骤是这样的:

  1. 初始化 sort_buffer,确定放入两个字段,即 name 和 id;

  2. 从索引 city 找到第一个满足 city='杭州’条件的主键 id

  3. 到主键 id 索引取出整行,取 name、id 这两个字段,存入 sort_buffer 中;

  4. 从索引 city 取下一个记录的主键 id;

  5. 重复步骤 3、4 直到不满足 city='杭州’条件为止,

  6. 对 sort_buffer 中的数据按照字段 name 进行排序;

  7. 遍历排序结果,取前 1000 行,并按照 id 的值回到原表中取出 city、name 和 age 三个字段返回给客户端。

我们可以看到 rowid 会多访问一次表,在mysql 看来,排序的复杂度高于回表的复杂度,这也是一种取舍。

综上可以看出不管是内存排序还是文件排序,都是很繁琐的,那么有没有对于这个问题有没有优化点了,在前面我们已经讲过了,索引一定是有序的,如果我们对city,name 建一个联合索引,就不用mysql 重新排序,因为索引本身就是有序的。

就是如下所示:

alter table t add index city_user(city, name);

但是上面虽然不用mysql 用文件排序,但是还是要回表的,那还有没有进一步的优化呢,我们可以考虑用覆盖索引

如下所示:

alter table t add index city_user_age(city, name, age);

这样就不用回表了,用explain 来看 Extra using index

大家要综合考虑吧,索引越多,索引越大,会影响插入的速度的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/461652.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WWW2024 | PromptMM:Prompt-Tuning增强的知识蒸馏助力多模态推荐系统

论文:https://arxiv.org/html/2402.17188v1 代码:https://github.com/HKUDS/PromptMM 研究动机 多模态推荐系统极大的便利了人们的生活,比如亚马逊和Netflix都是基于多模态内容进行推荐的。对于研究,人们也遵循工业界的趋势,进行modality-aware的用户…

生成器建造者模式(Builder)——创建型模式

生成器/建造者模式——创建型模式 什么是生成器模式? 生成器模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。 提炼两个关键点:Ⅰ.分步骤创建复杂对象。Ⅱ.相同创建代码…

北斗卫星在桥隧坡安全监测领域的应用及前景展望

北斗卫星在桥隧坡安全监测领域的应用及前景展望 北斗卫星系统是中国独立研发的卫星导航定位系统,具有全球覆盖、高精度定位和海量数据传输等优势。随着卫星导航技术的快速发展,北斗卫星在桥隧坡安全监测领域正发挥着重要的作用,并为相关领域…

python 目录和文件基本操作

目录操作 获取当前目录: import os dir_path os.getcwd() print("当前目录:", dir_path) 当前目录: D:\work\pycharm\object 创建目录: import osdir_path os.getcwd() print("当前目录:", d…

【算法刷题 | 栈】3.16(有效的括号、删除字符串中的所有相邻重复项、逆波兰表达式求值)

文章目录 1.有效的括号1.1题目1.2解法:栈 2.删除字符串中的所有相邻重复项2.1题目2.2解法:栈 3.逆波兰表达式求值3.1题目3.2解法:栈 1.有效的括号 1.1题目 给定一个只包括 (,),{,},[&#xff…

Midjourney绘图欣赏系列(十二)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子,它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同,Midjourney 是自筹资金且闭源的,因此确切了解其幕后内容尚不…

element ui 中文离线文档(百度云盘下载)

一般内网开发上不了网,用离线版本比较方便,下载地址: https://download.csdn.net/download/li836779537/88355878?spm1001.2014.3001.5503 下载后里面有个 index.hrml 双击打开就可以用 效果如下:

ADC架构III:Σ-Δ型ADC基础

简介 Σ-Δ型ADC是现代语音频带、音频和高分辨率精密工业测量应用所青睐的转换器。高度数 字架构非常适合现代细线CMOS工艺,因而允许轻松添加数字功能,而又不会显著增加成 本。随着此转换器架构的广泛使用,了解其基本原理显得非常重要。 历…

河南大学大数据平台技术实验报告二

大数据平台技术课程实验报告 实验二:HDFS操作实践 姓名:杨馥瑞 学号:2212080042 专业:数据科学与大数据技术 年级:2022级 主讲教师:林英豪 实验时间:2024年3月15日3点 至 2024年3月15日4点40 …

C#,入门教程(27)——应用程序(Application)的基础知识

上一篇: C#,入门教程(26)——数据的基本概念与使用方法https://blog.csdn.net/beijinghorn/article/details/124952589 一、什么是应用程序 Application? 应用程序是编程的结果。一般把代码经过编译(等)过程,最终形成的可执行 或 可再用 的文件称为应用程序。可执行文…

数据结构之顺序表(包学包会版)

目录 1.线性表 2.顺序表 2.1概念及结构 2.2接口实现 3.总结 halo,又和大家见面了,今天要给大家分享的是顺序表的知识,跟着我的脚步,包学包会哦~ 规矩不乱,先赞后看! ps:(孙权…

Android的三种动画详解(帧动画,View动画,属性动画)

Android的三种动画详解(帧动画、View动画、属性动画)_android动画效果大全-CSDN博客 1、帧动画 缺点是:占用内存较高,播放的是一帧一帧的图片,很少使用。 顺序播放预先定义的图片,类似于播放视频。 步骤…

MySQL语法分类 DDL

DDL(操作数据库、表) 数据库操作(CRUD) C(Create):创建 //指定字符集创建 create database db_1 character set utf8;//避免重复创建数据库报错可以用一下命令 create database if not exists db_1 character set utf8;R(Retrieve):查询 //查询所有数据库的名称 show datab…

基于ElasticSearch存储海量AIS数据:时空立方体索引篇

文章目录 引言I 时间维切分II 空间范围切分引言 索引结构制约着查询请求的类型和处理方式,索引整体架构制约着查询请求的处理效率。随着时间推移,AIS数据在空间分布上具备局部聚集性,如 果简单地将所有AIS数据插入一个索引结构,随着数据量增长,索引的更新效率、查询效率及…

8508A福禄克(FLUKE)数字多用表

181/2461/8938产品概述: Fluke 8508A 万用表在广泛的测量范围内具有卓越的准确性和稳定性,旨在用作校准实验室的多功能精密测量工具,这些实验室必须满足日益严格的测量不确定性分析要求以及提高生产率的需要。 作为其复杂职责的一部分&…

前端项目,个人笔记(一)【Vue-cli - 定制化主题 + 路由设计】

目录 1、项目准备 1.1、项目初始化 1.2、elementPlus按需引入 注:使用cnpm安装elementplus及两个插件,会报错:vueelement-plus报错TypeError: Cannot read properties of null (reading isCE ) ,修改: 测试&#…

SSO 单点登录

什么是JWT JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用间传输声明。它以一种紧凑且自包含的方式安全地在用户和服务之间传递信息,通常用于身份验证和信息交换 为什么要使用JWT 1.传统Se…

解密学习机制:线性回归与梯度下降之旅

摘要 在理解机器学习机制的过程中,我们探讨了在合成数据集上训练简单线性回归模型的过程。整个过程要解决的问题是算法如何通过迭代优化来学习输入和输出变量之间的基本关系。 我们的方法包括生成一个合成线性数据集,实施梯度下降进行参数估计&#xf…

Sonarqube中Java规则与CWE与OWASP的映射关系

很多企业使用Sonarqube社区版作为静态分析工具,在开发阶段检测代码中的缺陷或安全漏洞。但是如果是作为SAST工具厂商,集成该引擎,则需要把Sonarqube中的检测规则与其它引擎的规则进行整合,例如下图,把Sonarqube中的一些…

Spring Cloud Alibaba微服务从入门到进阶(三)(Spring Cloud Alibaba)

Spring Cloud Alibaba是spring Cloud的子项目 Spring Cloud Alibaba的主要组件(红框内是开源的) Spring Cloud是快速构建分布式系统的工具集, Spring Cloud提供了很多分布式功能 Spring Cloud常用子项目 项目整合 Spring Cloud Alibaba …