MySQL 排序的那些事儿

书接上回

上次发了几张图,给了几个MySQL Explain的场景,链接在这儿:你是不是MySQL老司机?来看看这些explain结果你能解释吗?MySQL 夺命6连问

我们依次来分析下这6个问题。

在分析之前,我们先来了解一下MySQL中的排序。
MySQL 排序主要有以下几种方式:

  1. 文件排序(Filesort)
  2. 索引排序(Index Order)

文件排序(Filesort)

文件排序还是比较有歧义的。字面意思就是使用文件排序,但是实际又不是只使用文件,根据具体情况而定,也就是文件排序不一定涉及磁盘文件的读写。

在使用文件排序算法时,MySQL会先尝试是不是可以在排序缓冲区(Sort Buffer)中排序,如果内存放不下要排序的数据集,MySQL才会选择使用磁盘临时文件。

这里有两个关键点需要注意:

  1. 先尝试排序缓冲区(Sort Buffer)排序,缓冲区大小不够才使用文件
  2. 使用文件是使用临时文件

我们只是MySQL有一个配置是Sort_buffer_size,用来配置一个连接的排序缓冲区,MySQL在排序时使用这个缓冲区。

file

另外一点就是临时文件,我们要知道临时文件不一定涉及文件读写,因为临时文件可能是在内存中也可能是在硬盘上。这个需要你根据实际情况来决定使用硬盘还是内存。如果使用基于内存的临时文件系统,那么在Linux临时文件系统中,向临时文件写数据会先写入内存,如果内存空间不足那么才会将内存中的数据交换到磁盘
看看kernel.org对临时文件系统的解释:

file

如果你使用硬盘的文件系统,比如:xfs,ext4等速度虽然不如tmpfs,但是更稳定。

怎么查询MySQL 临时文件配置

show variables like 'tmpdir'

COPY

file

我们看到值是/tmp,然后在使用df -h /tmp来查看是什么文件系统:

file

总结思考

以上两点让我们可以做一些优化:

  1. 如果涉及排序,可以把sort_buffer_size设置大点
  2. 如果使用Tmpfs就把MySQL物理内存配置的大点
  3. 如果使用xfs/ext4就用高速SSD硬盘

文件排序流程

当然,以下是结构化的过程描述:

  1. MySQL根据Where条件匹配行

  2. 然后在Sort Buffer中存一下排序所需要的列值(排序键值,行指针,以及查询所需的列)

  3. Sort Buffer满的时候使用快速排序算法进行排序,然后将排序好的数据写入临时文件中,同时还得记录一下这个文件,一般是记录文件描述符,就是一个int值(在Linux系统中)

  4. 对上面的步骤循环,直到所有扫描完所有Where条件匹配到的行

  5. 到这儿的时候,MySQL可能已经得到了非常多的临时文件(MySQL中交Chunk)

  6. 然后使用归并排序并和到一个结果文件

  7. 然后读取这个文件返回结果集

那么在使用Filesort进行排序是,MySQL使用快速排序对Sort buffer中的数据进行排序,然后使用归并排序对临时文件进行排序。
快排:

file

归并排:

file

索引排序(Index Order)

索引排序就比较简单了,就是如果查询可以使用索引,那么MySQL就使用扫描索引进行排序。如果是正序Explain的Extra列会显示空,如果是倒叙那么Explain就显示backword index scan

索引的组织结构就是B+树,天然有序。

Backward index scan是MySQL 8.0提供的优化特性。

几个例子

我们有一张trade_user表,表结构数据行数如下:

  1. 表结构

    file

  2. 数据行

file

使用文件排序

我们现在来使用name字段进行排序,

explain select * from trade_user order by name asc limit 10;

COPY

Type列为ALL,Extra列为Using filesort
这表示对trade_order表进行全表扫描,排序使用文件排序算法。
explain结果如下:

file

使用索引排序

现在我们修改一下表结构,对name字段增加索引:

alter table trade_user add index idx_name (name);
show indexes from trade_user;

COPY

我们可以看到idx_name索引是visible的,这是MySQL 8.0的新特性,索引是否对优化器可见。

file

我们来执行刚才的SQL:

explain select * from trade_user order by name asc limit 10;

COPY

这次我们执行会看到: Type列为Index, Extra列为NULL

file

这个就是使用了索引进行排序。

现在我们修改一下SQL,把asc修改为desc

explain select * from trade_user order by name desc limit 10;

COPY

我们看到输出和刚才的差别是:Extra列显示Backward index scan,这就是使用了MySQL 8.0的反向索引扫描

file

文件排序和索引排序的差别

文件排序

我们先把idx_name设置为不可见来分析下执行过程:

alter table trade_user alter index idx_name invisible;-- 这里我们添加一个analyze
explain analyze select * from trade_user order by name desc limit 10;

COPY

输出如下:

file

我们可以在输出中看到:

Table scan on trade_user  (cost=52799 rows=521335) (actual time=0.0305..236 rows=524991 loops=1)

COPY

这个SQL需要进行全表扫描,开销很大,数据行越多,开销越大。

索引排序

我们先把idx_name设置为可见来分析下执行过程:

alter table trade_user alter index idx_name visible;-- 这里我们添加一个analyze
explain analyze select * from trade_user order by name desc limit 10;

COPY

输出如下:

file

我们可以在输出中看到:

Index scan on trade_user using idx_name (reverse)  (cost=0.0128 rows=10) (actual time=1.76..1.79 rows=10 loops=1)

COPY

索引排序的开销就很小。

analyze怎么看

倒序看,我们看下我们刚才的两个输出怎么看:

-- 文件排序
3 -> Limit: 10 row(s)  (cost=52799 rows=10) (actual time=281..281 rows=10 loops=1)
2    -> Sort row IDs: trade_user.`name` DESC, limit input to 10 row(s) per chunk  (cost=52799 rows=521335) (actual time=281..281 rows=10 loops=1)
1        -> Table scan on trade_user  (cost=52799 rows=521335) (actual time=0.0382..221 rows=524991 loops=1)-- 索引排序1 -> Limit: 10 row(s)  (cost=0.0128 rows=10) (actual time=1.76..1.79 rows=10 loops=1)
2    -> Index scan on trade_user using idx_name (reverse)  (cost=0.0128 rows=10) (actual time=1.76..1

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GaussDB WDR分析之集群报告篇

AWR报告目前已经成为Oracle DBA分析问题,定位故障最为重要的报告,阅读与分析AWR报告的技能也是Oracle DBA必备的技能。国产数据库为了提高运维便捷性,都在做类似Oracle AWR报告的模仿,只不过由于指标体系不够完善,因此…

每日一题——LeetCode2549.统计桌面上的不同数字

方法一 模拟 维护一个数组arr&#xff0c;初始值为n,每次循环将arr[i] % j(1<j<n) 如果结果为1则将j加入&#xff0c; 最后将arr转为Set集合去重&#xff0c;Set的长度就是答案 var distinctIntegers function(n) {let arr[]arr.push(n)for(let i0;i<arr.length;i…

Spring Boot1

SpringBoot概述 Spring Boot是Spring提供的一个子项目&#xff0c;用于快速构建Spring应用程序 SpringBoot特性 起步依赖 本质上就是一个Maven坐标&#xff0c;整合了完成一个功能所需要的所有坐标 自动配置 遵循约定大于配置的原则&#xff0c;再boot程序启动后&#xff0…

阿里云4核16G服务器价格26.52元1个月、149.00元半年,ECS经济型e实例

阿里云4核16G服务器优惠价格26.52元1个月、79.56元3个月、149.00元半年&#xff0c;配置为阿里云服务器ECS经济型e实例ecs.e-c1m4.xlarge&#xff0c;4核16G、按固定带宽 10Mbs、100GB ESSD Entry系统盘&#xff0c;活动链接 aliyunfuwuqi.com/go/aliyun 活动链接打开如下图&a…

zookeeper快速入门(合集)

zookeeper作为一个分布式协调框架&#xff0c;它的创建就是为了方便或者简化分布式应用的开发。除了服务注册与发现之外&#xff0c;它还能够提供更多的功能&#xff0c;但是对于入门来说&#xff0c;看这一篇就够了。后续会讲zookeeper的架构设计与原理&#xff0c;比如zookee…

Docker入门到实践之环境配置

Docker入门到实践之环境配置 docker 环境安装 Ubuntu/Debian: sudo apt update sudo apt install docker.ioCentOS/RHEL: sudo yum install dockerArch Linux: sudo pacman -S docker如果未安装成功&#xff0c;或者env的path未设置成功&#xff0c;运行时会报错 Bash: Do…

怎么拆解台式电脑风扇CPU风扇的拆卸步骤-怎么挑

今天我就跟大家分享一下如何选购电脑风扇的知识。 我也会解释一下机箱散热风扇一般用多少转。 如果它恰好解决了您现在面临的问题&#xff0c;请不要忘记关注本站并立即开始&#xff01; 文章目录列表&#xff1a;大家一般机箱散热风扇都用多少转&#xff1f; 机箱散热风扇选择…

力扣501 二叉搜索树中的众数 Java版本

文章目录 题目描述代码使用非递归的方法使用递归的方法并且遍历的同时统计众数 题目描述 给你一个含重复值的二叉搜索树&#xff08;BST&#xff09;的根节点 root &#xff0c;找出并返回 BST 中的所有 众数&#xff08;即&#xff0c;出现频率最高的元素&#xff09;。 如果…

web自动化--元素定位之xpath和css

元素定位 xpath绝对路径相对路径案例xpath策略&#xff08;路径&#xff09;案例xpath策略&#xff08;层级、扩展&#xff09;属性层级与属性层级与属性拓展层级与属性综合 csscss选择器&#xff08;id、类、标签、属性&#xff09;id选择器类选择器标签选择器属性选择器案例-…

基于springboot+vue的旅游推荐系统

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、阿里云专家博主、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战&#xff0c;欢迎高校老师\讲师\同行交流合作 ​主要内容&#xff1a;毕业设计(Javaweb项目|小程序|Pyt…

亚稳态及其解决办法

异步电路 亚稳态 亚稳态亚稳态的产生原因什么是同步异步信号怎么消除亚稳态 亚稳态 在数字电路中&#xff0c;每一位数据不是1&#xff08;高电平&#xff09;就是0&#xff08;低电平&#xff09;。当然对于具体的电路来说&#xff0c;并非1&#xff08;高电平&#xff09;就是…

Flutter学习10 - Json解析与Model使用

对于网络请求返回的 Json 数据&#xff0c;一般会进行如下解析&#xff1a; 将 Json String 解析为 Map<String, dynamic>将 Json String 解析为 Dart Model 发起一个返回 Json String 的网络请求 import package:http/http.dart as http;void main() {_doGet(); }_do…

初始Java篇(JavaSE基础语法)(2)(逻辑控制)

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 目录 逻辑控制 顺序结构 分支结构 if语句 switch 语句 循环结构 while 循环 for 循环 do while 循环 输入输出 输出到控制台 从键盘输入 …

深度学习 tablent表格识别实践记录

下载代码&#xff1a;https://github.com/asagar60/TableNet-pytorch 下载模型&#xff1a;https://drive.usercontent.google.com/download?id13eDDMHbxHaeBbkIsQ7RSgyaf6DSx9io1&exportdownload&confirmt&uuid1bf2e85f-5a4f-4ce8-976c-395d865a3c37 原理&#…

Ubuntu安装教程——Desktop版本(细致入微的操作)

前言 首先我们准备Ubuntu的镜像文件 可以去Ubuntu的官方网站进行下载 https://ubuntu.com/download/desktop#get-ubuntu ubuntu-22.04.4-desktop-amd64.iso 一、安装Ubuntu桌面版操作系统 安装Ubuntu的操作系统的位置&#xff0c;方便管理和移动操作系统内的文件 使用镜像文…

pytest之统一接口请求封装

pytest之统一接口请求封装 pytest的requests_util.pyrequests_util.py 接口自动化测试框架的封装yaml文件如何实现接口关联封装yaml文件如何实现动态参数的处理yaml文件如何实现文件上传有参数化时候&#xff0c;怎么实现断言yaml的数据量大怎么处理接口自动化框架的扩展&#…

Qt播放音乐代码示例

主界面 点击play按钮播放或暂停音乐&#xff0c;拖动进度条&#xff0c;音乐对应播放。 QWidget window;QPushButton* playButton new QPushButton("Play");// Qt 播放音乐// 创建 QMediaPlayer 对象QMediaPlayer* player new QMediaPlayer;// 指定音频文件的路径…

DataV 在HTML中使用

一&#xff1a;什么是DataV 介绍 | DataV (jiaminghi.com) 组件库基于Vue &#xff08;React版 (opens new window)&#xff09; &#xff0c;主要用于构建大屏&#xff08;全屏&#xff09;数据展示页面即数据可视化&#xff0c;具有多种类型组件可供使用&#xff1a;…

鸿蒙一次开发,多端部署(九)应用市场首页

本小节将以应用市场首页为例&#xff0c;介绍如何使用自适应布局能力和响应式布局能力适配不同尺寸窗口。 页面设计 一个典型的应用市场首页的UX设计如下所示。 观察应用市场首页的页面设计&#xff0c;不同断点下的页面设计有较多相似的地方。 据此&#xff0c;我们可以将页…

【机器学习】决策树学习下篇(详解)

引言 在当今数据驱动的时代&#xff0c;机器学习技术已成为解决复杂问题不可或缺的工具。其中&#xff0c;决策树学习作为一种基础且强大的算法&#xff0c;广泛应用于各种领域&#xff0c;包括但不限于金融风控、医疗诊断、客户关系管理等。决策树以其简单直观、易于理解和实…