MySQL 中的数据排序实现

在 MySQL 中,数据排序是通过 ORDER BY 子句实现的,主要涉及 文件排序索引排序 两种方式。


1. 排序的基本原理

MySQL 的排序实现分为以下两种情况:

  • 文件排序(File Sorting):当排序无法利用索引优化时,MySQL 会通过排序算法和临时表完成。
  • 索引排序(Index Sorting):如果排序字段有索引,MySQL 可以直接利用索引的有序性完成排序,无需额外操作。

2. 文件排序

文件排序的过程

ORDER BY 子句为例:

SELECT * FROM users ORDER BY age DESC;

其工作流程如下:

  1. 提取排序字段

    • 提取查询所需的列和 ORDER BY 中的排序字段。
  2. 排序操作
    • 根据排序字段对数据进行排序,可能需要内存排序或磁盘排序。
  3. 返回排序结果
    • 排序完成后,将排序结果返回给客户端。

排序算法

  • 双路排序(Two-Pass Sorting)

    • 提取排序列和主键到临时区域,对这些数据排序后,再通过主键回表查询其他列。
  • 单路排序(Single-Pass Sorting)(MySQL 8.0 优化):
    • 直接提取所有需要的列,一次完成排序,避免二次回表。

排序缓冲

  • MySQL 优先在内存中完成排序,通过 sort_buffer_size 参数配置排序缓冲区大小。
  • 当数据量超过内存限制时,MySQL 会写入磁盘进行排序,性能较低。

3. 索引排序

MySQL 可以利用 B+ 树索引的有序性完成排序,从而避免文件排序。例如:

SELECT * FROM users ORDER BY id ASC;

索引排序的条件

  1. 排序列有索引:索引必须覆盖 ORDER BY 指定的排序字段。

  2. 复合索引顺序匹配

    • 如果是多列排序,索引的列顺序需与 ORDER BY 的顺序一致。
    SELECT * FROM users ORDER BY age, name;

    如果存在 (age, name) 索引,MySQL 可直接利用该索引排序。

  3. 排序方向一致

    • ORDER BY 中包含不同方向的排序(如 ORDER BY age ASC, name DESC),MySQL 无法直接利用索引。

覆盖索引

当查询仅涉及索引列时,MySQL 可直接利用覆盖索引返回结果,无需访问表。


4. 内存与磁盘排序

MySQL 的排序优先使用内存,当数据量过大时,才会使用磁盘:

  • 内存排序:在 sort_buffer_size 限定的范围内,所有数据均在内存中排序。
  • 磁盘排序:当数据量超过内存限制时,MySQL 会将部分数据写入磁盘临时表进行排序,性能相对较低。

5. 排序性能优化

(1)使用索引优化排序

  • 索引可以显著减少排序开销。
  • 对于多列排序,创建复合索引有助于优化查询性能。

(2)调整 sort_buffer_size

  • 增加 sort_buffer_size 大小,可以减少磁盘排序操作。
SET GLOBAL sort_buffer_size = 2M;

(3)减少排序数据量

  • 使用 LIMIT 限制返回行数,减少需要排序的数据。
SELECT * FROM users ORDER BY age LIMIT 100;

(4)避免不必要的排序操作

  • 避免使用 ORDER BY RAND(),因为它需要对所有数据进行随机排序,性能很差。
  • 避免在排序列上使用函数,如 ORDER BY UPPER(name)

6. 示例对比

文件排序

当无法使用索引时:

SELECT * FROM users WHERE age > 20 ORDER BY name;

MySQL 会提取满足条件的记录,并通过排序算法在内存或磁盘中完成排序。

索引排序

当排序列有索引时:

SELECT * FROM users WHERE age > 20 ORDER BY age;

MySQL 可以直接利用 age 列上的索引完成排序,无需额外操作。


7. 总结

  1. 文件排序:当没有合适的索引时,MySQL 使用文件排序对数据进行排序,可能涉及内存或磁盘操作。
  2. 索引排序:当排序列有索引时,MySQL 可直接利用索引的有序性完成排序。
  3. 优化建议
    • 合理设计索引结构,避免不必要的排序操作。
    • 调整排序缓冲区大小,减少磁盘排序的可能性。
    • 限制返回行数,减少排序数据量。

MySQL 中的数据排序是怎么实现的?的更多相关文章

  1. 辛星浅谈mysql中的数据碎片以及引擎为MyISAM下的操作

    对于mysql中的数据碎片,事实上和我们删除数据是息息相关的,删除数据的时候必定会在数据文件里造成不连续的空白空间,对于少量的数据的删除,并不会产生多少的空白空间.假设在一段时间内的大量的删除操作,会 ...

  2. Vusual C++连接Mysql和从MySql中取出数据的API介绍

    .1 mysql_real_connect() 2.1.1 函数原型: MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const ...

  3. DataSet 中的数据排序 及 DataRow装成DataTable

    1.DataSet 中的数据排序 DataSet ds = new DataSet(); // 获取当前排口的数据 ds = _xiaobill.GetHistoryData(yinZiBianm, ...

  4. 用python批量向数据库(MySQL)中导入数据

    用python批量向数据库(MySQL)中导入数据 现有数十万条数据,如下的经过打乱处理过的数据进行导入 数据库内部的表格的数据格式如下与下面的表格结构相同 Current database: pyt ...

  5. PHP如何批量更新MYSQL中的数据

    最近项目需要用到批量更新数据库里的数据,在网上找了一下这方面的例子,觉得这个还不错,分享给大家. 在这个业务里里面涉及到了更新两张数据表,那么大家是不是会想到非常简单,马上上代码 $sql ,type ...

  6. hadoop项目实战--ETL--(二)实现自动向mysql中添加数据

    四 项目开发 1 创建数据库db_etl,新建两张表user 和oder.表结构如第一部分图所示. 2 编写python脚本,实现自动向mysql中插入数据. 新建python 项目,目录结构如下图 ...

  7. PHP读取mysql中的数据

    <!DOCTYPE HTML> <html> <head> <title> PHP动态读取mysql中的数据 </title> <me ...

  8. PHP批量更新MYSQL中的数据

    原文链接:https://blog.csdn.net/wuming19900801/article/details/62893429 $sql = "update newhouse_clic ...

  9. MySQL_(Java)分页查询MySQL中的数据

    MySQL_(Java)使用JDBC向数据库发起查询请求 传送门 MySQL_(Java)使用JDBC创建用户名和密码校验查询方法 传送门 MySQL_(Java)使用preparestatement ...

  10. 利用Ajax实现数据的同步传输,从mysql中提取数据,通过echarts可视化

    如何将mysql数据库中的方式通过echarts可视化呢,以下面这个简单的例子向大家进行演示:   步骤一:mysql的创表和插入数据,当然这些数据也可以是你通过爬虫抓取的.     步骤二:   创 ...

随机推荐

  1. MapStruct入门使用

    MapStruct入门使用案例 以下是常用的使用举例,按照需求改动即可 @Data public class UserDO{ private int age; private String name; ...

  2. uni-app之条件编译

    ifdef 仅出现在XXx平台上 仅出现在 App 平台下的代码 #ifdef APP-PLUS 需条件编译的代码 #endif <!-- 只在H5上有哈 --> <!-- #ifd ...

  3. JUC并发—2.Thread源码分析及案例应用

    大纲 1.什么是线程以及并发编程 2.微服务注册中心案例 3.以工作线程模式开启微服务的注册和心跳线程 4.微服务注册中心的服务注册功能 5.微服务注册中心的心跳续约功能 6.微服务的存活状态监控线程 ...

  4. C# DataTable 类使用

    命名空间: System.Data 程序集: System.Data.Common.dll 参考连接:https://docs.microsoft.com/zh-cn/dotnet/api/syste ...

  5. npm配置

    在 Node.js 中,npm(Node Package Manager)是 JavaScript 包的默认管理工具.要查看 npm 的配置,你可以使用 npm config 命令配合不同的子命令来获 ...

  6. 【Python&Hypermesh】ABAQUS导入网格,并在Part内保留SET

    在Hypermesh定义好set,划分好网格以后,可以导出为INP.然后在ABAQUS导入inp,就可以得到网格.但是这样倒进来的网格一般有两个问题: 网格全在一个部件里,原来定义好的Set会出现在装 ...

  7. Selenium 报错 提示“unable to find an ant file to run”

    解决:我采用方法2解决成功 翻译:不能找到执行文件 出现问题原因:这个文件是我从电脑A拷贝到电脑B,缺少相应文件导致

  8. class com.ttsx.activity.item.dao.entity.RoleMenu ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method. 报错解决办法

    启动项目的时候,有几条WARN警告,如图: 引起原因: 是因为数据表实体类 没有di导致的. 例如: 解决办法: 增加实体id字段!或可以忽略!不影响程序!

  9. NumPy学习8

    今天学习了NumPy统计函数 16,NumPy统计函数 numpy_test8.py : import numpy as np ''' 16,NumPy统计函数 NumPy 提供了许多统计功能的函数, ...

  10. Joker 智能开发平台再推重磅新品,引领开发新潮流

    自 Joker 智能开发平台的前端可视化版本惊艳亮相后,便迅速在行业内掀起热潮,其创新的理念与出色的性能,为开发者和企业打造了高效.便捷的开发新路径,备受瞩目与好评.如今,Joker 智能开发平台即将 ...