首页 > 数据库 >【MySQL】order by 的排序策略

【MySQL】order by 的排序策略

时间:2024-08-18 17:23:43浏览次数:7  
标签:sort buffer 主键 索引 MySQL id 排序 order

目录

一、全字段排序

二、磁盘临时文件辅助排序

三、RowId 排序

四、优化 order by


在前面的文章中我们分析了 explain 执行计划的各个字段,其中有一个 Extra 字段。

在执行计划中,Extra 字段如有 Using filesort 则表示使用到了排序。

而 MySQL 的排序机制相当复杂,它会根据不同的情况选择最适合的排序策略。

一般来说,MySQL 会尝试利用索引来避免排序操作,但如果必须进行排序,它会尽可能地使用内存中的排序来提高效率。

当数据量过大时,MySQL 会使用磁盘上的临时文件来进行排序。

这些策略的选择取决于多种因素,包括表结构、索引、查询条件、系统资源等。

一、全字段排序

MySQL 会给每个查询线程分配一块小内存,用于排序的,称为 sort_buffer

什么时候把字段放进去排序呢,其实是通过索引找到对应的数据,才把数据放进去啦。 

 

整体的执行流程:

  1. MySQL 为对应的线程初始化 sort_buffer,放入需要查询的字段;

  2. 索引树找到第一个满足条件的主键 id;

  3. 主键 id 索引树拿到满足条件的这一行数据, 取查询的字段的值,存到sort_buffer;

  4. 索引树拿到下一个记录的主键 id;

  5. 重复步骤 3、4 直到不满足条件为止;

  6. 前面5步已经查找到了所有满足条件的数据,在 sort_buffer中,将所有数据进行排序;

  7. 按照排序结果返回给客户端。

此时就存在一个问题:如果数据太多,内存放不下怎么办? 

二、磁盘临时文件辅助排序

实际上,sort_buffer 的大小是由一个参数控制的:sort_buffer_size

如果要排序的数据小于 sort_buffer_size,排序在 sort_buffer 内存中完成,如果要排序的数据大于 sort_buffer_size,则借助磁盘文件来进行排序。

使用了磁盘临时文件,整个排序过程又是怎样的呢?

  1. 主键Id索引树,拿到需要的数据,并放到 sort_buffer 内存块中。当 sort_buffer 快要满时,就对 sort_buffer 中的数据排序,排完后,把数据临时放到磁盘一个小文件中。

  2. 继续回到主键 id 索引树取数据,继续放到 sort_buffer 内存中,排序后,也把这些数据写入到磁盘临时小文件中。

  3. 继续循环,直到取出所有满足条件的数据。最后把磁盘的临时排好序的小文件,合并成一个有序的大文件。

TIP: 借助磁盘临时小文件排序,实际上使用的是归并排序算法。

 

三、RowId 排序

rowid 排序就是,只把查询 SQL 需要用于排序的字段和主键id,放到 sort_buffer 中。

那怎么确定走的是全字段排序还是 rowid 排序排序呢?

实际上有个参数控制的。这个参数就是 max_length_for_sort_data,它表示 MySQL 用于排序行数据的长度的一个参数,如果单行的长度超过这个值,MySQL 就认为单行太大,就换 rowid 排序,我们可以通过命令看下这个参数取值。

使用 rowid 排序的话,整个 SQL 执行流程又是怎样的呢?

  1. MySQL 为对应的线程初始化 sort_buffer,放入需要排序的字段,以及主键 id;

  2. 索引树找到第一个满足条件的主键 id;

  3. 主键 id 索引树拿到满足条件的这一行数据, 取需要排序的字段和主键 id 的值,存到 sort_buffer;

  4. 索引树拿到下一个记录的主键 id;

  5. 重复步骤 3、4 直到不满足条件为止;

  6. 前面5步已经查找到了所有满足条件的数据,在 sort_buffer中,将所有数据根据需要排序的字段进行排序;

  7. 遍历排序结果,并按照 id 的值回到原表中,取出需要查询的字段返回给客户端。

 

对比一下全字段排序的流程,rowid 排序多了一次回表。 

回表是指在使用非主键索引进行查询时,数据库系统需要根据索引中获取的主键值回到数据表中获取完整行数据的过程。这种操作通常发生在索引不能直接提供查询所需的所有数据时。 

四、优化 order by

那可以如何优化 order by 语句呢?

  • 因为数据是无序的,所以就需要排序。如果数据本身是有序的,那就不用排了。而索引数据本身是有序的,我们通过建立联合索引,优化 order by 语句。

  • 还可以通过调整 max_length_for_sort_data 等参数优化;

可以建立联合索引,这样查询的数据就不需要用到内存排序了,在索引树上就是我们想要的顺序效果。

 

一  叶  知  秋,奥  妙  玄  心 

标签:sort,buffer,主键,索引,MySQL,id,排序,order
From: https://blog.csdn.net/weixin_43551213/article/details/141302039

相关文章

  • JDBC链接MySQL day18
    packagecom.shujia.day18.ketang;importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.Statement;/*我们要想操作mysql数据库,jdk本身是无法操作的,因为java并不知道将来开发者需要使用java连接什么样的数据库,所以j......
  • Java毕设源码-基于ssm框架的少儿编程网上报名系统+vue+毕业论文+mysql数据库
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求/流程分析3、系统功能结构三、系统实现展示1、管理员功能模块2、用户功能模块3、前台首页功能模块四、毕设内容和源代码获取总结逃逸的卡路里博主介绍:✌️码农一枚|毕设布道师,专注于......
  • Java毕设源码-ssm框架学院党员管理系统+jsp+vue+毕业论文+mysql数据库
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求/流程分析3、系统功能结构三、系统实现展示1、管理员功能实现1.1党员管理1.2支部管理1.3公告管理1.4党费管理1.5奖惩记录2、支部功能实现2.1基层单位2.2支部日志2.3支部荣誉3、党......
  • js数组排序
    快速排序:每次循环使用数组中间位置的值按照大小,将数组分成左右两个部分,使用递归,分别对左右两个部分执行分割操作1//快速排序2functionquickSort(arr){3if(arr.length<=1){4returnarr;5}6constmidIndex=Math.floor(arr.length......
  • 基于Java+SpringBoot+Mysql实现的共享厨房平台功能设计与实现六
    一、前言介绍:1.1项目摘要随着城市化进程的加快和人们对生活品质要求的提升,共享经济模式在全球范围内迅速兴起。共享厨房平台作为共享经济的一种创新形式,旨在通过整合闲置的厨房资源,为用户提供一个便捷、经济且富有创意的烹饪空间。现代都市生活中,许多年轻人、创业者及小......
  • 基于Java+SpringBoot+Mysql实现的共享厨房平台功能设计与实现七
    一、前言介绍:1.1项目摘要随着城市化进程的加快和人们对生活品质要求的提升,共享经济模式在全球范围内迅速兴起。共享厨房平台作为共享经济的一种创新形式,旨在通过整合闲置的厨房资源,为用户提供一个便捷、经济且富有创意的烹饪空间。现代都市生活中,许多年轻人、创业者及小......
  • 基于Java+SpringBoot+Mysql实现的共享厨房平台功能设计与实现四
    一、前言介绍:1.1项目摘要随着城市化进程的加快和人们对生活品质要求的提升,共享经济模式在全球范围内迅速兴起。共享厨房平台作为共享经济的一种创新形式,旨在通过整合闲置的厨房资源,为用户提供一个便捷、经济且富有创意的烹饪空间。现代都市生活中,许多年轻人、创业者及小......
  • 基于Java+SpringBoot+Mysql实现的共享厨房平台功能设计与实现六
    一、前言介绍:1.1项目摘要随着城市化进程的加快和人们对生活品质要求的提升,共享经济模式在全球范围内迅速兴起。共享厨房平台作为共享经济的一种创新形式,旨在通过整合闲置的厨房资源,为用户提供一个便捷、经济且富有创意的烹饪空间。现代都市生活中,许多年轻人、创业者及小......
  • PHP—MySQL(PHP连接数据库)
    目录【学习目标、重难点知识】【学习目标】【重难点知识】二、PHP和MySQL的合作方式三、PHP连接数据库3.1、MySQLi拓展​编辑3.2、建立与数据库的连接(4)创建SQL语句(5)获取结果(6)获取查询结果行数(7)增删改(8)数据可视化。【学习目标、重难点知识】【学习目标】P......
  • MySQL 查询分组内最新的第一条数据
    目录1、MySQL5版本的写法2、MySQL8版本的写法由于MySQL5不支持窗口函数,因此不能使用PARTITION()、ROW_NUMBER()......