✅order by 是怎么实现的?

首先排序功能由 ORDER BY 实现,具体排列顺序取决于优化器的选择。若优化器认为索引排序更有效率,则使用索引排序;反之,则使用 filesort(执行计划中额外信息提示:使用 filesort)。然而,索引排序的适用情况有限,且不确定性较高,通常还是会采用 filesort。

在 filesort 排序中,如果排序的数据较少,可在内存中的 sort_buffer 上完成;否则,需借助临时文件进行排序。实际排序过程中,如果字段长度较短,可直接在 sort_buffer 中进行全字段排序并返回结果集。若字段长度较长,可能出于空间考量,采用基于 row_id 的排序,此时会进行二次回表后返回结果集。

索引排序

众所周知,索引具备天然的排序属性,因此在使用 ORDER BY 时,若能充分利用索引,则效率必然最佳。

MySQL 确实可以基于索引执行 ORDER BY 查询,然而这一过程是否必然使用索引完全由优化器决定。

 CREATE TABLE `t2` (`id` INT(11),`a` varchar(64) NOT NULL,`b` varchar(64) NOT NULL,`c` varchar(64) NOT NULL,`d` varchar(64) NOT NULL,`f` varchar(64) DEFAULT NULL,PRIMARY KEY(id),UNIQUE KEY `f` (`f`),KEY `idx_abc` (`a`,`b`,`c`)KEY `idx_a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

假设存在如上所述的表格,在排序过程中可能会出现以下情况(由于优化器的干预,以下结果并不一定可以 100%复现。根据我的实验,在 MySQL 5.7 环境中是可以的)。

select * from t2 order by a;-- 不走索引,使用filesort(后面介绍啥是filesort)select * from t2 order by a limit 100;-- 走索引select a,b from t2 order by a limit 100;-- 走索引select a,b,c from t2 order by a;-- 走索引select a,b,c,d from t2 order by a;-- 不走索引,使用filesortselect a,b,c,d from t2 where a = "Paidaxing" order by b;-- 走索引select a,b,c,d from t2 where b = "Paidaxing" order by a;-- 不走索引,使用filesort

在使用索引字段进行排序时,优化器会根据成本评估来选择是否通过索引进行排序。经过我的多次验证,以下情况中,索引排序的概率较高:

  • 查询的字段和 ORDER BY 的字段组成了一个联合索引,并且查询条件符合最左前缀匹配,使得查询可以使用索引覆盖。例如:SELECT a, b, c FROM t2 ORDER BY a;
  • 查询条件中包含了 LIMIT,并且 LIMIT 的数量不是很大。(在我测试的表中,数据量为 80 万,当 LIMIT 超过 2 万多时就不再使用索引排序),例如:ORDER BY a LIMIT 100
  • 虽然未遵循最左前缀匹配,但是前导列通过常量进行了查询,例如:WHERE a = "Paidaxing" ORDER BY b

filesort 排序

如果无法使用或优化器认为索引排序效率不高,MySQL 将执行 filesort 操作,以读取表中的行并对它们进行排序。

在排序过程中,MySQL 为每个线程分配一块内存用于排序,称为sort_buffer,其大小由 sort_buffer_size控制。

根据 sort_buffer_size 的大小不同,排序操作会发生在不同的位置:

  • 如果排序数据量小于 sort_buffer_size,则排序在内存中完成。
  • 如果排序数据量大于 sort_buffer_size,则需要利用磁盘临时文件辅助排序。

临时文件排序采用归并排序算法,首先将需要排序的数据分配到多个临时文件中,同时进行排序操作,然后将多个排序完成的文件合并成一个结果集返回给客户端。
相对于在内存中的 sort_buffer 排序,磁盘上的临时文件排序速度较慢。

除了sort_buffer_size参数之外,影响排序算法的另一个关键参数是 max_length_for_sort_data

max_length_for_sort_data 是 MySQL 中控制用于排序的行数据的长度的一个参数,默认值为 1024 字节。如果单行长度超过该值,MySQL 就会认为单行太大,因此会采用 rowid 排序;否则,会进行全字段排序。

全字段排序

所谓全字段排序,即将要查询的所有字段都放入 sort_buffer 中,然后根据排序字段进行排序,排序完成后直接将结果集返回给客户端。

假设我们有以下查询 SQL:

select a,d,f from t2 where a = "Paidaxing" order by d;--

因为此处涉及的字段为 a、d、f 三个,因此将满足 WHERE 条件的所有数据的 a、d、f 字段都放入 sort_buffer 中,然后根据 d 字段在 sort_buffer 中进行排序,排序完成后返回给客户端的大致过程如下:

  1. 从索引 a 中取出满足条件 a = “Paidaxing” 的第一条记录的主键 ID。
  2. 根据主键 ID 回表,提取 a、d、f 三个字段的值,并将它们存入 sort_buffer。
  3. 继续查询下一个符合 a = “Paidaxing” 条件的记录,重复执行第 1 和第 2 步骤。
  4. 在 sort_buffer 中根据 d 字段进行排序。
  5. 将排序后的结果集返回给客户端。

image.png

以上过程中,如果数据在 sort_buffer 中无法全部存放,则会使用临时文件,并对临时文件进行归并排序。

全字段排序的优点在于只需要对原表进行一次回表查询(每条记录只需回表一次),排序完成后可以直接返回所需字段,因此效率较高。但其缺点在于,如果要查询的字段较多,会占用大量 sort_buffer 空间,导致可存储的数据量减少。当需要排序的数据量增大时,可能会使用临时文件,从而导致整体性能下降。

为避免这个问题,可以采用 row_id 排序的方式。

row_id 排序

这个也很好理解,即在构建 sort_buffer 时,不需要将所有要查询的字段都放进去,只需要将排序字段和主键放入即可。

select a,d,f from t2 where a = "Paidaxing" order by d;

比如这个 SQL,只需要将 d 和 id 放入 sort_buffer 中,首先按照 d 进行排序。排序完成后,根据 id 将对应的 a、d、f 几个字段查询出来,然后返回给客户端的大致过程如下:

  1. 从索引 a 中取出符合条件 a = “Paidaxing” 的第一条记录的主键 ID。
  2. 根据主键 ID 回表,提取 d 字段的值,并将其存入 sort_buffer。
  3. 继续查询下一个符合条件 a = “Paidaxing” 的记录,重复执行第 1 和第 2 步骤。
  4. 在 sort_buffer 中根据 d 进行排序。
  5. 根据排序后的 id,回表查询出对应的 a、d、f 几个字段。
  6. 将结果集返回给客户端。

image.png

以上的第五步,与全字段排序算法相比确实多了一次回表操作。因此,这种方案的效率肯定会稍慢一些。

如何选择

如何选择排序方式?

实际上,row_id 是 MySQL 的一种优化算法,它首先考虑使用全字段排序。只有在认为字段长度过长可能影响效率时,才会采用 row_id 排序方式。此外,如果能够利用 sort_buffer 完成排序,MySQL 就不会使用临时文件。

综上所述,MySQL 在选择排序方式时会优先考虑速度、内存和减少回表次数等因素。

如有问题,欢迎微信搜索【码上遇见你】。

免费的Chat GPT可微信搜索【AI贝塔】进行体验,无限使用。

好了,本章节到此告一段落。希望对你有所帮助,祝学习顺利。

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

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

相关文章

如何制定精益生产团队的目标和考核机制?

当下,精益生产已经成为企业追求高效运营和持续竞争优势的重要策略。而要实现精益生产的最大化效益,制定科学合理的团队目标与考核机制显得尤为重要。本文,深圳天行健企业管理咨询公司将分享如何制定精益生产团队的目标和考核机制,…

【Test 19】 数据结构 快速排序详解!

文章目录 1. 快速排序的非递归版本2. 快速排序2.1 hoare 版本一2.2 挖坑法 🐧版本二2.3 前后指针 版本三2.4 调用以上的三个版本的快排 3. 快速排序的优化 1. 快速排序的非递归版本 🆒🐧关键思路: 🍎① 参数中的begin…

vue3第三十六节(自定义插件)

一、首先什么是插件 插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。 主要应用于以下四个方面 1、通过 app.component() 和 app.directive() 注册一到多个全局组件或自定义指令。 2、通过 app.provide() 使一个资源可被注入进整个应用。 3、向 app.config.globalPro…

【乐吾乐3D可视化组态编辑器】数据集与数据订阅

对于物联网或者数字孪生项目来说,单纯的静态场景展示是无法满足需求的,它需要系统可以提供一种方式将后台数据与模型数据关联,当后台数据推送更新时,模型数据能自动同步。接下来,我们将向您介绍如何在系统中实现这一需…

Linux--线程的分离、线程库的地址关系的理解、线程的简单封装(二)

线程系列: 线程的认识:讲解线程的概念和线程的基本控制 线程的分离 线程分离是指将一个线程从主线程中分离出来,使其能够独立运行。当一个线程被设置为分离状态时,它结束时系统会自动回收其资源,而不需要其他线程使用…

ArcGIS空间数据处理、空间分析与制图;PLUS模型和InVEST模型的原理,参量提取与模型运行及结果分析;土地利用时空变化以及对生态系统服务的影响分析

工业革命以来,社会生产力迅速提高,人类活动频繁,此外人口与日俱增对土地的需求与改造更加强烈,人-地关系日益紧张。此外,土地资源的不合理开发利用更是造成了水土流失、植被退化、水资源短缺、区域气候变化、生物多样性…

北京大学第一医院与智源研究院共同发布基于可信执行环境的AI医学影像挑战赛

肾动脉狭窄是导致继发性高血压及肾功能不全的常见原因,而目前针对肾动脉狭窄功能学的评估尚处于探索阶段。数据保护和可信计算环境是目前人工智能技术应用于临床研究的一大瓶颈。北京大学第一医院与北京智源人工智能研究院心脏AI 联合研究中心特发布基于可信执行环境…

Ubuntu22.04之解决:Flameshot无法截图问题(二百三十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

Ant design vue的表格双击编辑功能(即双击开始编辑并自动获得焦点,失去焦点时完成编辑)

本文基于Ant Design Vue官方网站的表格(可编辑单元格)(表格 Table - Ant Design Vue (antdv.com))中的样板代码获得双击编辑且获得焦点、失去焦点时完成编辑的功能。 要点: (1)双击时候实现编辑&#xff…

如何使用Cloudways搭建WordPress网站(附最新Cloudways优惠码)

如今,搭建网站已经变得非常简单,这主要得益于开源的CMS建站系统的兴起。即使是不懂编程的人也能轻松搭建自己的网站,这些CMS系统提供了丰富的主题模板和插件,使用户可以通过简单的拖放和配置操作来建立自己的网站。 WordPress是目…

子网划分案例

4.2子网划分 “有类编址”的地址划分过于死板,划分的颗粒度太大,会有大量的主机号不能被充分利用,从而造成了大量的IP地址资源浪费。因此可以利用子网划分来减少地址浪费,即VLSM (Variable Length Subnet Mask),可变长…

国内前十款专业外盘期货交易app软件排名盘点(综合版)

随着社会经济的不断发展,现在投资者倾向于投资各种项目以获取超额收益。在选择外盘期货交易app软件时,有几个关键的因素需要考虑。首先是软件的可靠度和安全度,因为交易涉及到实际资金。因此,需要选择具备专业资质、经验丰富、充分…

Android下HWC以及drm_hwcomposer普法(上)

Android下HWC以及drm_hwcomposer普法(上) 引言 按摩得全套,错了,做事情得全套,普法分析也是如此。drm_hwcomposer如果对Android图形栈有一定研究的童鞋们应该知道它是Android提供的一个的图形后端合成处理HAL模块的实现。但是在分析这个之前…

汽车悬架分为哪几类

汽车悬架分为哪几类 1)汽车的悬架系统可根据结构分为两种:独立悬架和非独立悬架,独立悬架根据构造又可以分为CDC运动悬架(CDC电磁悬架系统)和空气悬架; 2)当前比较火热的空气悬架,是独立悬架的一种; 3)前轮主要使用麦弗逊式独立悬架 和 双叉臂悬架,后轮主要使用多…

倒角距离【Chamfer Distance】

倒角距离(chamfer distance)是用于评估两组点之间的相似度的度量。给定两个点集 A 和 B,倒角距离定义为 A 中每个点到 B 中最近邻点的距离之和,加上 B 中每个点到 A 中最近邻点的距离之和。它用于各种应用,包括计算机视…

每期一个小窍门 k8s版本的 Prometheus + grafana + alertmanager 三件套部署监控落地

首先部署prometheus 首先是pvc apiVersion: v1 kind: PersistentVolumeClaim metadata:name: prometheus-data-pvcnamespace: monitor spec:accessModes:- ReadWriteManystorageClassName: "data-nfs-storage"resources:requests:storage: 10Gi然后接着 cluster-ro…

CSS+Canvas绘制最美星空(一闪一闪亮晶晶效果+流星划过)

1.效果 2.代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><style>body,html {margin: 0;padding: 0;ov…

20 VUE学习:插件

介绍 插件 (Plugins) 是一种能为 Vue 添加全局功能的工具代码。下面是如何安装一个插件的示例&#xff1a; import { createApp } from vueconst app createApp({})app.use(myPlugin, {/* 可选的选项 */ })一个插件可以是一个拥有 install() 方法的对象&#xff0c;也可以直接…

CNAS软件测试公司作用分享,如何获取CNAS软件测试报告?

在软件测试行业&#xff0c;CNAS认可和CNAS软件测试公司是不可忽视的关键词。CNAS认可是指中国合格评定国家认可委员会对特定领域组织、机构或公司的能力和资质进行的认可过程。该认可遵循国际标准及相关法律法规&#xff0c;是评定组织或实验室技术能力和专业水平的权威认可&a…

【考研数学】李艳芳900比李林880难吗?值得做吗?

差不多&#xff0c;只能说基础没搞好刷这两个都很费劲 李艳芳900题把每个章节题目划分为ABC三个难度级别&#xff0c;题目选取的难度较大也比较新颖&#xff0c;计算量也非常接近考研趋势&#xff0c;原创性很高&#xff0c;比较适合过完一轮的同学继续做补充和强化 880算是比…