首页 > 数据库 >MySQL-文件排序原理详解

MySQL-文件排序原理详解

时间:2024-06-22 16:27:40浏览次数:25  
标签:sort buffer 双路 filesort 单路 详解 MySQL 排序

目录

Using filesort文件排序原理详解

filesort文件排序方式

示例验证下各种排序方式:

单路排序的详细过程:

双路排序的详细过程:

单路排序相对于双路排序具有以下特点:


Using filesort文件排序原理详解

filesort文件排序方式

  • 单路排序:是一次性取出满足条件行的所有字段,然后在sort buffer中进行排序;用trace工具可以看到sort_mode信息里显示< sort_key, additional_fields >或者< sort_key,packed_additional_fields >
  • 双路排序(又叫回表排序模式):是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行 ID,然后在 sort buffer 中进行排序,排序完后需要再次取回其它需要的字段;用trace工具可以看到sort_mode信息里显示< sort_key, rowid >

MySQL 通过比较系统变量 max_length_for_sort_data(默认1024字节) 的大小和需要查询的字段总大小来判断使用哪种排序模式。

  • 如果 字段的总长度小于max_length_for_sort_data ,那么使用 单路排序模式;
  • 如果 字段的总长度大于max_length_for_sort_data ,那么使用 双路排序模式。

示例验证下各种排序方式:

查看下这条sql对应trace结果如下(只展示排序部分):

mysql> set session optimizer_trace="enabled=on",end_markers_in_json=on;  --开启trace
mysql> select * from employees where name = 'zhuge' order by position;
mysql> select * from information_schema.OPTIMIZER_TRACE;

trace排序部分结果:
"join_execution": {    --sql执行阶段
        "select#": 1,
    "steps": [
        {
            "filesort_information": [
                {
                    "direction": "asc",
                    "table": "`employees`",
                    "field": "position"
                }
            ] /* filesort_information */,
            "filesort_priority_queue_optimization": {
                "usable": false,
                "cause": "not applicable (no LIMIT)"
            } /* filesort_priority_queue_optimization */,
            "filesort_execution": [] /* filesort_execution */,
            "filesort_summary": {                      --文件排序信息
              "rows": 10000,                           --预计扫描行数
              "examined_rows": 10000,                  --参与排序的行
              "number_of_tmp_files": 3,                --使用临时文件的个数,这个值如果为0代表全部使用的sort_buffer内存排序,否则使用的磁盘文件排序
              "sort_buffer_size": 262056,              --排序缓存的大小,单位Byte
              "sort_mode": "<sort_key, packed_additional_fields>"       --排序方式,这里用的单路排序
            } /* filesort_summary */
        }
    ] /* steps */
} /* join_execution */
      
      
mysql> set max_length_for_sort_data = 10;    --employees表所有字段长度总和肯定大于10字节
mysql> select * from employees where name = 'zhuge' order by position;
mysql> select * from information_schema.OPTIMIZER_TRACE;

trace排序部分结果:
"join_execution": {
    "select#": 1,
    "steps": [
        {
            "filesort_information": [
                {
                    "direction": "asc",
                    "table": "`employees`",
                    "field": "position"
                }
            ] /* filesort_information */,
            "filesort_priority_queue_optimization": {
                "usable": false,
                "cause": "not applicable (no LIMIT)"
            } /* filesort_priority_queue_optimization */,
            "filesort_execution": [] /* filesort_execution */,
            "filesort_summary": {
                "rows": 10000,
                "examined_rows": 10000,
                "number_of_tmp_files": 2,
                "sort_buffer_size": 262136,
                "sort_mode": "<sort_key, rowid>"         --排序方式,这里用的双路排序
            } /* filesort_summary */
        }
    ] /* steps */
} /* join_execution */


mysql> set session optimizer_trace="enabled=off";    --关闭trace

单路排序的详细过程:

1. 从索引name找到第一个满足 name = ‘zhuge’ 条件的主键 id

2. 根据主键 id 取出整行,取出所有字段的值,存入 sort_buffer 中

3. 从索引name找到下一个满足 name = ‘zhuge’ 条件的主键 id

4. 重复步骤 2、3 直到不满足 name = ‘zhuge’

5. 对 sort_buffer 中的数据按照字段 position 进行排序

6. 返回结果给客户端

双路排序的详细过程:

1. 从索引 name 找到第一个满足 name = ‘zhuge’ 的主键id

2. 根据主键 id 取出整行,把排序字段 position 和主键 id 这两个字段放到 sort buffer 中

3. 从索引 name 取下一个满足 name = ‘zhuge’ 记录的主键 id

4. 重复 3、4 直到不满足 name = ‘zhuge’

5. 对 sort_buffer 中的字段 position 和主键 id 按照字段 position 进行排序

6. 遍历排序好的 id 和字段 position,按照 id 的值回到原表中取出 所有字段的值返回给客户端

其实对比两个排序模式,单路排序会把所有需要查询的字段都放到 sort buffer 中,而双路排序只会把主键和需要排序的字段放到 sort buffer 中进行排序,然后再通过主键回到原表查询需要的字段。如果 MySQL 排序内存 sort_buffer 配置的比较小并且没有条件继续增加了,可以适当把max_length_for_sort_data 配置小点,让优化器选择使用双路排序算法,可以在sort_buffer 中一次排序更多的行,只是需要再根据主键回到原表取数据。如果 MySQL 排序内存有条件可以配置比较大,可以适当增大 max_length_for_sort_data 的值,让优化器优先选择全字段排序(单路排序),把需要的字段放到 sort_buffer 中,这样排序后就会直接从内存里返回查询结果了。

所以,MySQL通过 max_length_for_sort_data 这个参数来控制排序,在不同场景使用不同的排序模式,从而提升排序效率。

注意:如果全部使用sort_buffer内存排序一般情况下效率会高于磁盘文件排序,但不能因为这个就随便增大sort_buffer(默认1M),mysql很多参数设置都是做过优化的,不要轻易调整。

单路排序相对于双路排序具有以下特点:
  • 单路排序只需要一次I/O操作,而双路排序需要两次I/O操作,因此在磁盘I/O方面,单路排序效率更高。
  • 双路排序需要进行归并排序的阶段,这涉及到更多的内存操作和排序操作,相对于单路排序来说,性能可能稍差一些。
  • 在数据量小于内存容量的情况下,单路排序通常比双路排序更快,因为它不需要额外的归并操作。

然而,在处理大于内存容量的数据集时,双路排序具有明显的优势,因为它可以有效地处理超出内存大小的排序需求。

标签:sort,buffer,双路,filesort,单路,详解,MySQL,排序
From: https://blog.csdn.net/qq_45061342/article/details/139871584

相关文章

  • Docker部署MySQL8.3.0(保姆级图文教程)
    系列文章目录Docker部署Nginx1.21.5(保姆级图文教程)Docker部署MySQL8.3.0(保姆级图文教程)文章目录一、环境二、拉取镜像2.1查找DockerHub上的MySQL镜像2.2拉取MySQL镜像2.3查看MySQL镜像三、在宿主机创建目录3.1创建挂载目录3.2创建配置文件四、启动MySQL......
  • mysqladmin——MySQL Server管理程序(二)
    mysqladmin 是一个命令行工具,用于执行简单的MySQL服务器管理任务,如检查服务器的状态、创建和删除数据库、重载权限等。1reload重新加载授权表(granttables)。当修改了MySQL的权限系统(例如,修改了用户权限或添加了新用户),需要重新加载授权表以使这些更改生效。使用FLUSHPRIV......
  • mysqladmin——MySQL Server管理程序(一)
    mysqladmin 是一个命令行工具,用于执行简单的MySQL服务器管理任务,如检查服务器的状态、创建和删除数据库、重载权限等。调用mysqladmin如下:mysqladmin[options]command[command-arg][command[command-arg]]...mysqladmin支持以下命令。有些命令在命令名后面带有一个......
  • DCF协议详解
    1概述DCF机制是IEEE802.11标准的核心接入机制,网络中所有节点都应该具备该功能。DCF主要采用带有冲突避免的载波侦听多路访问(CarrierSenseMultipleAccessCollisionAvoidance,CSMA/CA)协议,当使用CSMA时,一个想要发送数据的站点首先侦听传输煤质一段定长时间,如果......
  • 使用MPI 实现奇偶排序
    使用MPI实现奇偶排序0号进程获得待排序序列并输出排序好的序列使用文件进行输入输出进行性能测试与对比代码奇偶排序头文件引入#include<iostream>#include<algorithm>#include<mpi.h>#include<fstream>#include<chrono>定义规模#defineN100000000......
  • Python 冒泡排序
    冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。以下是一个用Python实现的冒泡排序算法的例子:pythondefbubble_sort(lst):n=len......
  • [MySQL总结] Explain详解、索引最佳优化
    目录ExplainExplain分析示例explain两个变种explain中的列1.id列2.select_type列3.table列4.type列5.possible_keys列6.key列7.key_len列8.ref列9.rows列10.Extra列索引最佳优化实践1.全值匹配2.最左前缀法则3.不在索引列上做任何操作(计算、函数、(自动or......
  • MySQL总结-索引优化实战详解一
    目录一、索引下推优化详解1.联合索引第一个字段用范围不会走索引2.强制走索引3.覆盖索引优化4.in和or在表数据量比较大的情况会走索引,在表记录不多的情况下会选择全表扫描5.likeKK%一般情况都会走索引索引下推(IndexConditionPushdown,ICP)为什么范围查找Mysql没有......
  • 在Linux中,mysql 数据备份工具有哪些?
    在Linux中,MySQL数据备份工具有多种选择,这些工具在功能、性能和易用性上有所不同。以下是一些常用的MySQL数据备份工具及其特点:mysqldump描述:mysqldump是MySQL自带的一个命令行工具,用于执行逻辑备份。它通过导出SQL语句来备份数据库,可以备份表结构、数据以及视图等。优点:备......
  • 在Linux中,如何重置 mysql root 密码?
    在Linux系统中重置MySQL的root密码通常有几种方法,以下是一些常见的步骤:1.使用mysqladmin命令首先,停止MySQL服务:sudosystemctlstopmysql以安全模式启动MySQL,允许root用户无密码登录:sudomysqld_safe--skip-grant-tables&连接到MySQL服务器:mysql-uroot选......