MySQL是如何处理排序的(最新推荐)

 更新时间:2024年05月16日 09:35:37   作者:华为云开发者联盟  
在MySQL的查询中常常会用到order by和group by这两个关键字,它们的相同点是都会对字段进行排序,那查询语句中的排序是如何实现的呢,下面跟随小编一起看看吧

前言

在MySQL的查询中常常会用到order bygroup 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排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • mysql表分区的方式和实现代码示例

    mysql表分区的方式和实现代码示例

    通俗地讲表分区是将一个大表,根据条件分割成若干个小表,下面这篇文章主要给大家介绍了关于mysql表分区的方式和实现代码,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-02-02
  • MySql使用skip-name-resolve解决外网链接客户端过慢问题

    MySql使用skip-name-resolve解决外网链接客户端过慢问题

    在腾讯云上面搭建的mysql使用开发的电脑上navicat进行访问时总是特别的慢,原来是Mysql会对请求的地址进行域名解析,开发的电脑并没有域名,所以会导致特别的慢,下面通过本文给大家分享MySql使用skip-name-resolve解决外网链接客户端过慢问题
    2017-07-07
  • 在同一台机器上运行多个 MySQL 服务

    在同一台机器上运行多个 MySQL 服务

    在同一台机器上运行多个 MySQL 服务...
    2006-11-11
  • MySQL存储时间类型选择的问题讲解

    MySQL存储时间类型选择的问题讲解

    今天小编就为大家分享一篇关于MySQL存储时间类型选择的问题讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • MySQL窗口函数 over(partition by)的用法

    MySQL窗口函数 over(partition by)的用法

    本文主要介绍了MySQL窗口函数 over(partition by)的用法, partition by相比较于group by,能够在保留全部数据的基础上,只对其中某些字段做分组排序,下面就来介绍一下具体用法,感兴趣的可以了解一下
    2024-02-02
  • 详解MySQL如何保证数据一致性

    详解MySQL如何保证数据一致性

    对于一个数据库而言,除了数据的持久性、不丢失之外,一致性也是非常重要的,不然这个数据是没有任何意义的,在使用MySQL时,数据不一致的情况也可能出现,所以,本文就来看看MySQL是如何保证数据一致的,需要的朋友可以参考下
    2024-01-01
  • MySQL中无过滤条件的count详解

    MySQL中无过滤条件的count详解

    这篇文章主要给大家介绍了关于MySQL中无过滤条件count的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧
    2019-02-02
  • MySQL数据库中使用REPLACE函数示例及实际应用

    MySQL数据库中使用REPLACE函数示例及实际应用

    本文详细介绍了MySQL中的REPLACE函数,包括其基本语法、用法和实际应用场景,REPLACE函数主要用于替换字符串中的某些子字符串,对大小写敏感,文章还通过多个示例展示了REPLACE函数的实际应用,需要的朋友可以参考下
    2024-10-10
  • MYSQL数据库如何设置主从同步

    MYSQL数据库如何设置主从同步

    大家好,本篇文章主要讲的是MYSQL数据库如何设置主从同步,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • Java实现获得MySQL数据库中所有表的记录总数可行方法

    Java实现获得MySQL数据库中所有表的记录总数可行方法

    可以通过SELECT COUNT(*) FROM table_name查询某个表中有多少条记录。本文给出两种可行的Java程序查询所有别的记录方法,感兴趣朋友可以了解下
    2013-06-06

最新评论