聊聊MySQL是如何处理排序的
本文分享自华为云社区《MySQL怎样处理排序️如何优化需要排序的查询?》,作者:菜菜的后端私房菜。
前言
在MySQL的查询中常常会用到 order by 和 group by 这两个关键字
它们的相同点是都会对字段进行排序,那查询语句中的排序是如何实现的呢?
当使用的查询语句需要进行排序时有两种处理情况:
- 当前记录本来就是有序的,不需要进行排序
- 当前记录未保持顺序,需要排序
使用索引保证有序
对于第一种情况,常常是使用二级索引中索引列的有序来保证结果集有序,从而不需要进行排序
对于表a,为a2建立二级索引,那么在二级索引上a2就是有序的
CREATE TABLE `a` (
`a1` int(11) NOT NULL AUTO_INCREMENT,
`a2` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL,
`a3` varchar(255) DEFAULT NULL,
PRIMARY KEY (`a1`),
KEY `idx_a2` (`a2`)
) ENGINE=InnoDB AUTO_INCREMENT=76 DEFAULT CHARSET=utf8;
select * from a order by a.a2 limit 10
当优化器选择使用a2索引时,a2列的记录本身就是有序的,因此不需要再使用其他开销进行排序

当然,优化器也有可能不使用a2索引(当优化器认为使用a2回表开销太大时会使用全表扫描)

当优化器使用的索引上a2无序时,则会通过其他手段对结果进行排序
filesort
当执行计划的Extra附加信息中出现 Using filesort 时,会使用sort_buffer对结果进行排序
sort_buffer是一块用于排序的内存,sort_buffer可能存放查询需要的所有字段,也可能只存放需要排序的字段和主键
show variables like 'max_length_for_sort_data'
当查询需要的字段长度小于 max_length_for_sort_data 时,则会将查询需要的所有字段放入sort_buffer中,然后对需要排序的列进行排序,最后返回结果

当查询需要的字段长度大于 max_length_for_sort_data 时,只会将需要排序的字段和主键值放入sort_buffer中,等到排序后再去查询聚簇索引获取需要查询的列(相当于又多了一次回表)

在sort_buffer中进行排序时,如果内存足够则会在内存中进行排序,如果内存不够则会使用磁盘的临时文件来辅助排序
开启 optimizer_trace 可以查看是否使用临时文件辅助排序
#开启优化器追踪
SET optimizer_trace='enabled=on';
#sql语句
select * from student order by student_name limit 10000;
#查看优化器追踪的信息
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G;
排序使用的算法是归并算法,先分割成多个小文件排序再进行合并
其中number_of_tmp_files 为使用到的临时文件数量,sort_buffer_size 为sort_buffer大小

因此当使用order by、group by等需要排序的关键字时,最好建立合适的索引
如果数据量小可以在sort buffer中排序,如果数据量太大还需要与磁盘交互
总结
当查询语句需要排序时会分为不用排序和需要排序两种情况
当使用的索引有序时则不用再进行排序,通过索引来保证有序
当使用的索引无序时则会使用sort_buffer进行排序,当查询字段的长度未超过限制时,sort_buffer中每条记录会存储需要查询的列
如果超过限制,则sort_buffer只会存储需要排序的列和主键值,排序后再通过主键值进行回表获取需要查询的列
当数据量太大不够在内存中排序完,会使用磁盘页辅助排序,使用归并算法将排序数据分散在多个页再合并
可以通过追踪优化器 optimizer_trace 分析内容查看辅助页的数量等信息
为需要排序的列建立合适的索引,避免使用磁盘页辅助排序
当无法使用索引时可以调整sort buffer 或 max_length_for_sort_data(谨慎)
聊聊MySQL是如何处理排序的的更多相关文章
- 聊聊Mysql索引和redis跳表 ---redis的有序集合zset数据结构底层采用了跳表原理 时间复杂度O(logn)(阿里)
redis使用跳表不用B+数的原因是:redis是内存数据库,而B+树纯粹是为了mysql这种IO数据库准备的.B+树的每个节点的数量都是一个mysql分区页的大小(阿里面试) 还有个几个姊妹篇:介绍 ...
- 聊聊MySQL的加锁规则《死磕MySQL系列 十五》
大家好,我是咔咔 不期速成,日拱一卒 本期来聊聊MySQL的加锁规则,知道这些规则后可以判断SQL语句的加锁范围,同时也可以写出更好的SQL语句,防止幻读问题的产生,在能力范围内最大程度的提升MySQ ...
- Mysql数据库表排序规则不一致导致联表查询,索引不起作用问题
Mysql数据库表排序规则不一致导致联表查询,索引不起作用问题 表更描述: 将mysql数据库中的worktask表添加ishaspic字段. 具体操作:(1)数据库worktask表新添是否有图片字 ...
- Oracle 实现 mysql 的 find_in_set 排序!
oracle 实现类似MYSQL的 find_in_set 排序,函数 decode: select * from tb_info_game where gameid in(23,20,19,26,1 ...
- mysql 分组内 排序
mysql 分组内 排序 类似于 sqlserver over partition by 因为mysql中木有sqlserver over partition by这个函数,要从sqlserver ...
- Mysql 内部默认排序
mysql默认的排序: https://forums.mysql.com/read.php?21,239471,239688#msg-239688 Do not depend on order whe ...
- Mysql order by 排序 varchar 类型数据
Mysql order by 排序 varchar 类型数据 varchar 类型字段排序, 会將数字当成字符串来处理. 排序规则一般是从左到右一位位来比较. +0之后 就转化成INT 类型排序 ...
- MySQL字符集与排序规则总结
字符集与排序规则概念 在数据库当中都有字符集和排序规则的概念, 很多开发人员甚至包括有些DBA都会将这个混淆,当然这个情况也有一些情有可原的原因.一来两者本来就是相辅相成,相互依赖关联: 另外一方 ...
- MySQL 多列排序
MySQL 基础篇 三范式 MySQL 军规 MySQL 配置 MySQL 用户管理和权限设置 MySQL 常用函数介绍 MySQL 字段类型介绍 MySQL 多列排序 MySQL 行转列 列转行 M ...
- 聊聊MySQL常用的4种主从复制架构
目录 一主多从复制架构 多级复制架构 双主(Dual Master)复制架构 多源(Multi-Source)复制架构 如何优化主从延迟问题? 复制的4中常见架构有一主多从复制架构.多级复制架构.双主 ...
随机推荐
- mysql系列之杂谈(一)
从刚开始工作到现在,除了实习的时候在国企用过oracle,毕业之后陪伴我的数据库一直都是mysql,而由于mysql的开源特性,也让成为无数公司的宠儿,越走越远. 我们在刚开始使用mysql时,会发现 ...
- sqli_lab Less1练习笔记
首先观察页面信息,看有没有提示. 很显然,这个页面让我们传入id这个参数(根据题目的分支,应该是get方法) 使用HackBar进行传入参数,首先传入id=1 http://localhost/sql ...
- identity4 系列————用户数据持久化篇[六]
前言 前面的例子已经将各种情形下的例子已经介绍了一遍,那么后面就是用户数据持久化该如何处理了. 正文 例子位置: https://github.com/IdentityServer/IdentityS ...
- deepspeed 训练多机多卡报错 ncclSystemError Last error
最近在搞分布式训练大模型,踩了两个晚上的坑今天终于爬出来了 我们使用 2台 8*H100 遇到过 错误1 10.255.19.85: ncclSystemError: System call (e.g ...
- ABP -Vnext框架一步一步入门落地教程——ABP Vnext框架代码安装和启动(一)
兄弟们,人生需要指引,而复制是成功最快的方式,让我们开始行动吧 --codesoft 教程介绍 ABP-Vnext框架我们之前摸了无数次,好象初恋的女孩,一直在靠近,一直在努力,一直不敢盯着她的眼睛说 ...
- maven报错:501 HTTPS Required
maven报错:501 HTTPS Required 简单来说,如果报错中出现http://repo1.maven.org/maven2/的字样的话,那么大概率就是Maven仓库的设置里的地址有问题, ...
- 力扣429(java)-构造矩形(简单)
题目: 作为一位web开发者, 懂得怎样去规划一个页面的尺寸是很重要的. 所以,现给定一个具体的矩形页面面积,你的任务是设计一个长度为 L 和宽度为 W 且满足以下要求的矩形的页面.要求: 你设计的矩 ...
- 通过Jenkins构建CI/CD实现全链路灰度
简介: 本文介绍通过 Jenkins 构建流水线的方式实现全链路灰度功能. 作者:卜比 本文介绍通过 Jenkins 构建流水线的方式实现全链路灰度功能. 在发布过程中,为了整体稳定性,我们总是希 ...
- 了解3D世界的黑魔法-纯Java构造一个简单的3D渲染引擎
简介: 对于非渲染引擎相关工作的开发者来说,可能认为即使构建最简单的3D程序也非常困难,但事实上并非如此,本篇文章将通过简单的200多行的纯 Java代码,去实践正交投影.简单三角形光栅化.z缓冲(深 ...
- 阿里云2020上云采购季,你最pick哪个产品组合?
阿里云2020上云采购季如火如荼进行中,活动还剩最后10天啦,你的云产品都买好了吗? 还没买的,还没逛的,请戳:https://www.aliyun.com/sale-season/2020/proc ...