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在排序时使用这个缓冲区。

c99402412bb04c4a76c749fa9e4614a2.png

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

0e53cae9da40f0c7840117703be47ca0.png

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

怎么查询MySQL 临时文件配置

show variables like 'tmpdir'

COPY

 

68b405d2f4cb0ec71f8b8f6d28a5e9d2.png

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

f67caad0f6e4bbe28e6558dbf98b3457.png

总结思考

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

  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中的数据进行排序,然后使用归并排序对临时文件进行排序。
快排:

8c3fe234c136a9a7d1dac9df4d8e4bac.png

归并排:

9486832c5355f6992184804d2b03f408.png

索引排序(Index Order)

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

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

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

几个例子

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

  1. 表结构

    2af2fbb37ba8db0837a58ce53787e0cb.png

  2. 数据行

 

9cae7c8ddad6359b191b03a01bb09998.png

使用文件排序

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

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

COPY

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

ec0b329f9314764aea4911168caf52c8.png

使用索引排序

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

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

COPY

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

9928c80b44cbfc05862f67b72efed8a4.png

我们来执行刚才的SQL:

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

COPY

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

9ab91281e9476fa6938fc8de8297af38.png

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

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

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

COPY

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

b2788f7f34d611fe5001bded0ef2f811.png

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

文件排序

我们先把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

输出如下:

64b90c9aaace4d5b8bb4d61183c763ba.png

我们可以在输出中看到:

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

输出如下:

60370403b49f8890fa4512287a630503.png

我们可以在输出中看到:

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.mzph.cn/news/767349.shtml

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

相关文章

操作系统面经-用户态和内核态

字节实习生带你面试,后台私信可以获得面试必过大法!! 根据进程访问资源的特点,我们可以把进程在系统上的运行分为两个级别: 用户态(User Mode) : 用户态运行的进程可以直接读取用户程序的数据,拥有较低的…

【蓝牙协议栈】【BLE】低功耗蓝牙配对绑定过程分析(超详细)

1. 精讲蓝牙协议栈(Bluetooth Stack):SPP/A2DP/AVRCP/HFP/PBAP/IAP2/HID/MAP/OPP/PAN/GATTC/GATTS/HOGP等协议理论 2. 欢迎大家关注和订阅,【蓝牙协议栈】和【Android Bluetooth Stack】专栏会持续更新中.....敬请期待&#xff01…

Three.js 中的 OrbitControls 是一个用于控制相机围绕目标旋转以及缩放、平移等操作的控制器。

demo案例 Three.js 中的 OrbitControls 是一个用于控制相机围绕目标旋转以及缩放、平移等操作的控制器。下面是它的详细讲解: 构造函数: OrbitControls(object: Camera, domElement?: HTMLElement)object:THREE.Camera 实例,控制器将围绕…

从零开始学习在VUE3中使用canvas(五):globalCompositeOperation(图形混合)

一、简介 通过设置混合模式来改变图像重叠区域的显示方式。 const ctx canvas.getContext("2d");ctx.globalCompositeOperation "source-over"; 二、属性介绍 source-over 这是默认的复合操作。将源图像绘制到目标图像上,保留目标图像的不透…

IPV6协议之DHCPV6

目录 背景: 一、DHCPV6概述 DHCPv6 Client: DHCPv6 Relay: DHCPv6 Server: 二、DHCPV6工作原理 DHCPV6无状态自动分配 三、DHCP基础配置 服务端 四、DHCPV6地址更新时间(DHCPV4租期) 五、DHCPV6…

idea 开发serlvet篮球秩序册管理系统idea开发mysql数据库web结构计算机java编程layUI框架开发

一、源码特点 idea开发 java servlet 篮球秩序册管理系统是一套完善的web设计系统mysql数据库 系统采用serlvetdaobean mvc 模式开发,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 servlet 篮…

☆【前后缀】【双指针】Leetcode 42. 接雨水

【前后缀】【双指针】Leetcode 42. 接雨水 解法1 前后缀分解解法2 双指针 ---------------🎈🎈42. 接雨水 题目链接🎈🎈------------------- 解法1 前后缀分解 维护一个前缀(左侧最高)后缀(右侧…

【Linux系统编程(进程编程)】进程的退出:父进程等待子进程的退出之僵尸进程与孤儿进程

文章目录 一、进程退出1.1、进程正常退出方式1.2、异常退出 二、父进程等待子进程退出(一)2.1、为什么要等待子进程退出2.2、(1)父进程等待子进程退出并收集子进程的退出状态如何等待wstatus空wstatus非空 2.3、(2&…

LeetCode---389周赛

题目列表 3083. 字符串及其反转中是否存在同一子字符串 3084. 统计以给定字符开头和结尾的子字符串总数 3085. 成为 K 特殊字符串需要删除的最少字符数 3086. 拾起 K 个 1 需要的最少行动次数 一、字符串及其反转中是否存在同一子字符串 直接暴力枚举即可,代码…

【PHP + 代码审计】数组函数

🍬 博主介绍👨‍🎓 博主介绍:大家好,我是 hacker-routing ,很高兴认识大家~ ✨主攻领域:【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 🎉点赞➕评论➕收…

力扣面试150 x 的平方根 二分 换底法 牛顿迭代法 一题多解

Problem: 69. x 的平方根 思路 👨‍🏫 参考题解 💖 袖珍计算器算法 class Solution {public int mySqrt(int x){if (x 0)return 0; // Math.exp(3):e的三次方int ans (int) Math.exp(0.5 * Math.log(x));return (long) (an…

配置环境安装包遇到的问题

1. error: could not install packages due to an oserror: [errno 28] no space left on device 说是磁盘占用过多,查看磁盘占用情况。 df -h 果然占比100% 清理了众多缓存.cache都不行,而且其他利用率很低,可能是pip install的过程中使…

qt 实现 轮播图效果,且还有 手动 上一页和下一页 已解决

QT中有 轮播图的需求,按照正常html版本 。只需要配置数组就能搞定,但是c qt版本 应该用什么了。 第一想到的是采用定时器。 // 定时器初始化{m_pTime new QTimer(this);m_pTime->start(4 * 1000);//启动定时器并设置播放时间间隔m_pAutoFlag true;/…

【python】python turtle绘制坤坤打球

一、效果图: 二、准备工作 (1)、导入必要的模块: 代码首先导入了需要使用的模块:requests、lxml和csv。 import requests from lxml import etree import csv 如果出现模块报错 进入控制台输入:建议使用国内镜像源 p…

智慧公厕:跨界融合,打造智慧城市新名片

随着城市化进程的不断加快,公共厕所建设成为一个亟待解决的问题。传统的公厕存在着管理繁琐、卫生差、服务不到位等一系列问题,与城市发展的节奏不协调。为此,推进新型智慧公厕建设成为了一个重要的解决方案。智慧公厕的建设需要推进技术融合…

【论文精读】VIT:vision transformer论文

相关文章 【论文精读】Transformer:Attention Is All You Need 文章目录 相关文章一、文章概览(一)研究背景(二)核心思路(三)相关工作(三)文章结论 二、模型细节&#x…

【MySQL系列】优化数据库时区设置,确保数据一致性与准确性

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

图论基础|深度优先dfs、广度优先bfs

dfs 与 bfs 区别 提到深度优先搜索(dfs),就不得不说和广度优先搜索(bfs)有什么区别 先来了解dfs的过程,很多录友可能对dfs(深度优先搜索),bfs(广度优先搜索…

鸿蒙Harmony应用开发—ArkTS-@Observed装饰器和@ObjectLink装饰器:嵌套类对象属性变化

上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二…

MySQL--select count(*)、count(1)、count(列名) 的区别你知道吗?

MySQL select count(*)、count(1)、count(列名) 的区别? 这里我们先给出正确结论: count(*),包含了所有的列,会计算所有的行数,在统计结果时候,不会忽略列值为空的情况。count(1),忽略所有的列…