详解Mysql Order by排序底层原理

        MySQL 的 ORDER BY 子句实现排序是一个涉及查询优化、内存管理和磁盘 I/O 的复杂过程。其核心目标是高效地将结果集按照指定列和顺序排列

一、确定排序模式 (Sort Mode)

MySQL 根据查询特性和系统变量决定采用哪种排序策略:

1.1 Rowid 排序

  • <sort_key, rowid> 模式 (Rowid 排序):

    • 仅将排序键 (ORDER BY 的列) 和 行指针 (通常是主键或行 ID) 放入 sort_buffer 内存缓冲区。

    • 在内存中对这些 <sort_key, rowid> 元组进行排序。

    • 排序完成后,根据行指针回表查询完整的数据行。

    • 优点: sort_buffer 能容纳更多元组,减少内存不足时落磁盘的次数。

    • 缺点: 排序后需要额外的回表操作,可能增加随机 I/O。

    • 触发条件: max_length_for_sort_data 系统变量设置较小,或者 SELECT 的列总长度较大时,优化器倾向于选择此模式。

1.2 全字段排序

  • <sort_key, additional_fields> 模式 (全字段排序):

    • 将 排序键 (ORDER BY 的列) 和 查询需要返回的所有列 放入 sort_buffer

    • 在内存中直接对包含完整数据的元组进行排序。

    • 排序完成后,直接从 sort_buffer 返回结果,无需回表

    • 优点: 避免排序后的回表操作,减少随机 I/O。

    • 缺点: 如果查询返回的列很多或很宽,sort_buffer 能容纳的元组数量会显著减少,更容易触发磁盘临时文件。

    • 触发条件: max_length_for_sort_data 设置较大,或者查询返回的列总长度较小时,优化器倾向于选择此模式。

1.3 打包排序

  • <sort_key, packed_additional_fields> 模式 (打包排序 - MySQL 8.0+ 优化):

    • MySQL 8.0.20 引入的进一步优化。

    • 类似于全字段排序,但对 sort_buffer 中存储的额外字段进行了更紧凑的打包处理。

    • 优点: 比传统全字段排序更节省 sort_buffer 空间,容纳更多数据,减少落盘。

    • 触发条件: MySQL 8.0.20 及以后版本默认启用,替代传统的全字段排序。

二、利用 sort_buffer 内存排序

  • MySQL 分配一块称为 sort_buffer 的内存区域专门用于排序。

  • 服务器线程将需要排序的行(根据选择的模式,可能是部分列或全列)放入 sort_buffer

  • 如果 sort_buffer 足够容纳所有需要排序的行

    • MySQL 直接在内存中对数据进行排序。通常使用高效的快速排序 (Quicksort) 算法。

    • 对于 ORDER BY ... LIMIT N 这类只需要前 N 条结果的查询,MySQL 优化器可能使用优先级队列 (Priority Queue Heap Sort) 算法。它在内存中维护一个大小为 N 的堆,只保留最终需要的 N 条有序结果,避免对所有数据进行完全排序,极大提升效率。

三、处理大数据集:外部排序 (External Sort)

  • 如果 sort_buffer 无法容纳所有需要排序的行

    • 分块排序: MySQL 会将数据分成若干块 (chunks)。对每一块数据在 sort_buffer 中进行快速排序,然后将排好序的块写入磁盘上的临时文件。这个过程称为 "run generation"。

    • 多路归并 (Multi-way Merge): 当所有块都排序并写入临时文件后,MySQL 使用归并排序 (Merge Sort) 算法将这些已排序的块合并成一个完整有序的结果集。它使用一个缓冲区同时读取多个临时文件的开头部分,找出当前最小的元素输出,然后从相应文件补充新元素,直到所有文件处理完毕。

    • 归并路数: 同时合并的文件数由 merge_buffer_size 控制。MySQL 会尽量多路归并以减少磁盘 I/O 轮次。

四、返回结果

  • 无论排序是在内存中完成还是经过外部排序,最终都会得到一个完全按照 ORDER BY 要求排序的结果集。

  • 服务器按顺序读取这个有序的结果集并返回给客户端。

五、关键影响因素和优化点:

  • sort_buffer_size 控制分配给每个排序操作的内存缓冲区大小。增大它可以减少甚至避免磁盘临时文件的使用,提升排序速度。但设置过大可能导致系统内存资源紧张(尤其是在高并发排序时)。

  • max_length_for_sort_data 决定优化器选择 Rowid 排序还是全字段/打包排序的阈值。增大它可能促使优化器选择全字段/打包排序(避免回表),但可能导致 sort_buffer 容纳行数减少(更容易落盘)。需要根据实际情况权衡。

  • tmpdir 指定磁盘临时文件的存储目录。使用更快的存储设备(如 SSD)可以显著提升外部排序阶段的速度。

  • ORDER BY ... LIMIT N 优化器会优先尝试使用优先级队列算法,性能通常很好。

  • 使用覆盖索引: 如果 ORDER BY 的列和 SELECT 的列都包含在一个索引中(覆盖索引),MySQL 可以直接按索引顺序读取数据,完全避免排序操作 (Using index)。这是性能最优的方式。

  • innodb_disable_sort_file_cache (InnoDB 相关) 控制是否对临时文件使用操作系统文件缓存。在某些场景下禁用可能有轻微性能提升。

  • 监控指标:

    • Sort_merge_passes: 归并排序的次数。次数多表明外部排序发生频繁,可能需要增大 sort_buffer_size

    • Sort_range / Sort_scan: 分别表示通过范围扫描和全表扫描执行的排序次数。

    • Sort_rows: 排序的总行数。

    • Created_tmp_disk_tables / Created_tmp_files: 创建的磁盘临时表和临时文件数,反映内存排序不足的情况。

六、总结流程:

  • 合理设计索引(尤其是覆盖索引)来避免排序。

  • 根据查询特征和服务器配置调整 sort_buffer_size 和 max_length_for_sort_data

  • 解读执行计划 (EXPLAIN) 中的 Using filesort(表示发生了排序)并判断其成本。

  • 监控服务器状态以识别潜在的排序性能瓶颈。

  • 编写更高效的 SQL 查询(例如,利用 LIMIT 优化)。

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

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

相关文章

SpringBoot的介绍和项目搭建

SpringBoot是简化Spring应用开发的一个框架&#xff0c;他是Spring技术栈的整合。优点&#xff1a;能够快速创建独立运行的Spring项目以及与主流框架集成使用嵌入式的Servlet容器&#xff0c;应用无需打成war包&#xff0c;内嵌tomcatStarters自动依赖和版本控制大量的自动装配…

Selenium 攻略:从元素操作到 WebDriver 实战

在自动化测试、网页数据爬取、批量操作网页等场景中&#xff0c;Selenium 无疑是最受欢迎的工具之一。作为一款强大的 Web 自动化工具&#xff0c;它能模拟人类操作浏览器的行为&#xff0c;实现点击、输入、跳转等一系列动作。本文将从基础到进阶&#xff0c;全面解析 Seleniu…

【算法训练营Day14】二叉树part4

文章目录找树左下角的值路径总和总结&#xff1a;递归函数的返回值路径总和 II总结&#xff1a;二叉树递归的思考从中序与后序遍历序列构造二叉树找树左下角的值 题目链接&#xff1a;513. 找树左下角的值 解题逻辑&#xff1a; 使用层序遍历&#xff0c;将最后一层的第一个元…

工资系统如何计算工资

工资系统计算工资是一个集成数据收集、规则应用、自动核算和合规审核的自动化过程&#xff0c;以下是其核心原理和步骤&#xff0c;结合技术实现与法规要求进行说明&#xff1a;⚙️ 一、工资系统的基本框架与数据准备系统初始化与规则配置企业信息设置&#xff1a;录入公司名称…

车载通信架构 --- DoIP协议通信

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 钝感力的“钝”,不是木讷、迟钝,而是直面困境的韧劲和耐力,是面对外界噪音的通透淡然。 生活中有两种人,一种人格外在意别人的眼光;另一种人无论…

基于Event Sourcing和CQRS的微服务架构设计与实战

基于Event Sourcing和CQRS的微服务架构设计与实战 业务场景描述 在电商系统中&#xff0c;订单的高并发写入与复杂的状态流转&#xff08;下单、支付、发货、退货等&#xff09;给传统的CRUD模型带来了挑战&#xff1a; 数据一致性难保证&#xff1a;跨服务事务处理复杂&#x…

初级安全课第二次作业

&#xff08;一&#xff09;xss-labs 1~8关 1、前期准备 &#xff08;1&#xff09;打开小皮面板&#xff0c;并启动Apache和MySQL&#xff08;2&#xff09;将 xss-labs放到 phpstudy_pro 的 WWW 目录下&#xff08;3&#xff09;访问连接&#xff1a;http://localhost/xss-la…

从零搭建智能搜索代理:LangGraph + 实时搜索 + PDF导出完整项目实战

传统的AI聊天系统往往局限于预训练数据的知识范围&#xff0c;无法获取实时信息。本文将详细阐述如何构建一个基于LangGraph的智能代理系统&#xff0c;该系统能够智能判断何时需要进行网络搜索、有效维护对话上下文&#xff0c;并具备将对话内容导出为PDF文档的功能。 本系统…

C语言分支和循环语句——猜数字游戏

分支语句的语法形式1. if(表达式)语句;2. if(表达式)语句1;else语句2;3. Switch(表达式){ case 1: break;case 2: break;case 3: break; default: break; }循环语句的语法形式1. while(表达式)语句 ;2. for&#xff08;表达…

Python设计模式深度解析:原型模式(Prototype Pattern)完全指南

Python设计模式深度解析&#xff1a;原型模式&#xff08;Prototype Pattern&#xff09;完全指南前言什么是原型模式&#xff1f;模式的核心组成实际案例&#xff1a;游泳比赛管理系统游泳者数据结构原型模式的实现深拷贝 vs 浅拷贝&#xff1a;核心概念解析浅拷贝&#xff08…

SAP-ABAP:SAP万能长度计算:DYNAMIC_OUTPUT_LENGTH 深度解析

&#x1f4cf; SAP ABAP 万能长度计算&#xff1a;DYNAMIC_OUTPUT_LENGTH 深度解析核心作用&#xff1a;智能计算数据对象在列表/ALV中的实际显示宽度 | 关键优势&#xff1a;多字节字符处理 | 格式感知 | 动态适配&#x1f50d; 一、核心功能与技术特性 &#x1f4ca; 数据类型…

20250720-2-Kubernetes 调度-资源限制对Pod调度的影响(1)_笔记

一、创建一个Pod的工作流程&#xfeff;1. k8s架构解析&#xfeff;组件交互模式: Kubernetes采用list-watch机制的控制器架构&#xff0c;实现组件间交互的解耦。各组件通过监控自己负责的资源&#xff0c;当资源发生变化时由kube-apiserver通知相关组件。类比说明: 类似小卖铺…

mobaxteam x11传输界面避坑

mobaxteam x11传输界面避坑 文章目录mobaxteam x11传输界面避坑1 windows系统必须下载xing2 配置1 windows系统必须下载xing 因为windows系统本身没有x服务。 2 配置 如图

flink sql如何对hive string类型的时间戳进行排序

在 Flink SQL 中对 Hive 表的 STRING 类型时间戳进行排序&#xff0c;需要先将字符串转换为时间类型&#xff0c;再基于时间类型排序。以下是具体方法和示例&#xff1a; 一、核心解决方案 1. 字符串转 TIMESTAMP 后排序 若 Hive 中的时间戳格式为 yyyy-MM-dd HH:mm:ss&#xf…

Linux:线程控制

线程概念线程&#xff08;Thread&#xff09;是进程&#xff08;Process&#xff09; 中的一个执行单元&#xff0c;是操作系统能够进行运算调度的最小单位。线程也被称为“轻量级进程”&#xff08;Lightweight Process, LWP&#xff09;。一个进程可以包含多个线程&#xff0…

React 学习(4)

核心API———createRoot、render方法1.createRoot 方法是创建react的根容器&#xff0c;就是react元素的插入位置&#xff0c;插入的dom会被转化成react元素&#xff0c;根容器内的内容都会被react管理&#xff0c;原有dom都会被删除。react17 根容器创建、渲染方式&#xff0…

ASP .NET Core 8集成Swagger全攻略

Swagger (现在称为 OpenAPI) 是一个用于描述 RESTful API 的规范&#xff0c;ASP.NET Core 内置支持通过 Swashbuckle 库生成 Swagger 文档。以下是在 ASP.NET Core 8 中实现 Swagger 的完整步骤。1、添加Swagger NuGet 包dotnet add package Swashbuckle.AspNetCore2、添加Swa…

【iOS】源码阅读(六)——方法交换

文章目录方法交换什么是Method-Swizzling方法交换核心API**1. 获取方法对象****2. 添加/替换方法实现****3. 交换方法实现****4. 获取方法信息****5. 修改方法实现****使用示例&#xff1a;完整的 Method-Swizzling 流程****注意事项**使用方法交换注意事项线程安全方法交换的影…

mysql运维问题解决:MySQL主从延迟(锁阻塞与读写分离)

小亦平台会持续给大家科普一些运维过程中常见的问题解决案例&#xff0c;运维朋友们可以在常见问题及解决方案专栏查看更多案例 问题概述 告警事件&#xff1a; 2023-07-28 03:31:39.571 首次触发主从延迟告警&#xff08;延迟1515秒&#xff09;2023-07-28 07:41:37 告警解除…

SSH 密钥

什么是 SSH 密钥 SSH 密钥就像是你电脑的“身份证”和“钥匙”&#xff0c; 用来安全登录另一台电脑&#xff08;服务器&#xff09;&#xff0c;而不需要每次输入密码。SSH 密钥是一种安全登录远程服务器的方式&#xff0c;由一对加密的“钥匙”组成&#xff1a;一个公钥 一个…