MySQL 中的排序:索引排序与文件排序
文章目录
- MySQL 中的排序:索引排序与文件排序全解析
- 一、引言
- 二、索引排序
- (一)原理
- (二)示例
- 三、文件排序
- (一)单路排序
- (二)双路排序
- (三)归并排序
- 四、优化建议
MySQL 中的排序:索引排序与文件排序全解析
一、引言
在 MySQL 数据库的查询操作中,排序是一项极为关键的任务。当执行查询并要求结果集按照特定顺序呈现时,MySQL 会依据多种因素来抉择合适的排序策略。其中,索引排序和文件排序是最为常见的两种方式,而文件排序又进一步细分为单路排序、双路排序以及归并排序。透彻理解这些排序机制对于优化数据库查询性能、提升系统响应速度具有不可忽视的重要性。
二、索引排序
(一)原理
索引在 MySQL 中是一种特殊的数据结构,它能够加速数据的检索与排序过程。当查询语句中的 ORDER BY 子句所涉及的字段与某个索引的列顺序完全匹配,并且索引的排序方向(升序或降序)也与 ORDER BY 要求一致时,MySQL 便可巧妙地利用该索引来完成排序操作。由于索引本身就按照特定规则对数据进行了有序存储,因此借助索引排序能够避免对数据行进行额外的读取与复杂排序运算,从而显著提升查询效率。
(二)示例
假设我们创建了一个名为 employees 的表,其结构如下:
CREATE TABLE employees (id INT AUTO_INCREMENT PRIMARY KEY,first_name VARCHAR(50),last_name VARCHAR(50),hire_date DATE,salary DECIMAL(10, 2),INDEX idx_hire_date (hire_date)
);
我们向表中插入一些示例数据:
INSERT INTO employees (first_name, last_name, hire_date, salary) VALUES
('John', 'Doe', '2020-01-01', 5000.00),
('Jane', 'Smith', '2021-03-15', 6000.00),
('Bob', 'Johnson', '2019-11-20', 4500.00);
现在执行一个查询:
SELECT * FROM employees ORDER BY hire_date;
使用 EXPLAIN 关键字来查看该查询的执行计划:
EXPLAIN SELECT * FROM employees ORDER BY hire_date;
在 EXPLAIN 的输出结果中,我们可以看到 Extra 列显示为 Using index,这就表明 MySQL 成功地运用了索引排序。它直接从索引中获取了按照 hire_date 有序的数据,无需进行额外的文件排序操作,从而大大提高了查询的执行速度。
三、文件排序
当查询条件无法利用索引进行排序时,MySQL 就不得不诉诸文件排序。文件排序意味着 MySQL 需要将数据读取到内存中进行排序处理,如果内存空间不足以容纳所有待排序的数据,还可能会借助磁盘临时表来辅助完成排序任务。
(一)单路排序
- 原理
- 单路排序的核心思想是将查询所需的全部列数据一次性地读取到内存中的排序缓冲区。在这个缓冲区中,MySQL 运用高效的排序算法(如快速排序等)对数据进行排序操作。这种方式在内存资源较为充裕且待排序数据量相对不大的情况下,能够展现出较高的效率。因为它避免了多次数据读取操作,减少了磁盘 I/O 开销以及数据在内存与磁盘之间的传输延迟。
- 单路排序的效率与
sort_buffer_size系统变量密切相关。sort_buffer_size用于指定排序缓冲区的大小。如果该值设置过小,可能导致排序过程中需要频繁地将部分数据临时存储到磁盘上,从而降低排序性能;反之,若设置过大,可能会占用过多的内存资源,影响系统中其他进程的运行。
- 示例
考虑如下查询:
SELECT first_name, last_name, salary FROM employees ORDER BY salary;
由于在 salary 字段上没有合适的索引可供利用,MySQL 将会执行文件排序。执行 EXPLAIN 命令查看该查询的执行计划:
EXPLAIN SELECT first_name, last_name, salary FROM employees ORDER BY salary;
在 EXPLAIN 结果中,我们会发现 Extra 列显示 Using filesort,这表明 MySQL 正在进行文件排序操作。此时,如果我们查看服务器的性能监控指标,会发现内存使用量在排序过程中会有所增加,并且主要集中在排序缓冲区的使用上。
(二)双路排序
- 原理
- 双路排序采用了一种更为巧妙的策略,尤其是在内存资源有限但索引列数据量相对较小的场景下表现出色。它首先仅读取查询所需列的索引数据以及对应的主键值到排序缓冲区进行排序。在完成初步排序后,再根据主键值回表读取剩余的列数据。这样做的好处在于,在内存有限的情况下,可以有效减少排序缓冲区中数据的占用量,因为只读取了索引列和主键值,而不是全部列数据。然而,这种方式也存在一定的代价,那就是需要额外的回表操作来获取完整的列数据,这可能会增加一定的磁盘 I/O 开销。
- 双路排序的决策过程也与
max_length_for_sort_data系统变量有关。该变量用于限制排序数据行的最大长度。当查询结果集中的列数据长度超过max_length_for_sort_data所设定的值时,MySQL 更倾向于选择双路排序,以避免一次性将大量数据读取到内存中。
- 示例
假设我们执行以下查询:
SELECT * FROM employees ORDER BY last_name;
如果 last_name 字段有索引,但并非覆盖索引(即查询所需的所有列并非都包含在该索引中),MySQL 可能会采用双路排序策略。通过 EXPLAIN 查看查询计划:
EXPLAIN SELECT * FROM employees ORDER BY last_name;
在 EXPLAIN 的输出中,Extra 列显示 Using filesort,并且在进一步分析数据库的执行日志或者性能监控数据时,可以观察到在排序过程中存在回表操作的迹象,如磁盘读取操作的增加以及相关统计指标的变化。
(三)归并排序
- 原理
- 当需要排序的数据量极为庞大,以至于无法在内存中一次性完成整个排序过程时,MySQL 会启用归并排序算法。归并排序采用了分治的思想,它首先将大规模的数据划分为多个较小的子数据集,然后在内存中分别对这些子数据集进行排序。排序完成后,再逐步将这些有序的子数据集合并成最终的有序结果集。在这个过程中,如果内存不足以容纳所有的子数据集,MySQL 会借助磁盘临时表来存储中间结果,这就不可避免地会带来磁盘 I/O 开销。不过,归并排序具有良好的稳定性和时间复杂度特性,能够在处理大规模数据排序时保持相对高效的性能表现。
- 示例
考虑如下查询:
SELECT * FROM employees ORDER BY RAND();
由于 ORDER BY RAND() 要求对数据进行随机排序,几乎不可能利用索引来实现,并且当 employees 表的数据量较大时,MySQL 就会采用归并排序进行文件排序。执行 EXPLAIN 命令查看该查询的执行计划:
EXPLAIN SELECT * FROM employees ORDER BY RAND();
在 EXPLAIN 结果中,Extra 列会显示 Using filesort。同时,在数据库服务器的资源监控中,我们可以明显观察到磁盘 I/O 活动的显著增加,这是因为归并排序过程中需要频繁地在磁盘临时表中写入和读取中间排序结果。
四、优化建议
- 合理创建索引:仔细分析查询语句中的
ORDER BY子句以及其他过滤条件,创建合适的索引,尽量使ORDER BY字段能够与索引匹配,从而优先利用索引排序,减少文件排序的发生频率。 - 优化
sort_buffer_size和max_length_for_sort_data:根据数据库服务器的内存配置以及实际业务需求,合理调整sort_buffer_size和max_length_for_sort_data系统变量的值。对于内存较为充裕且经常进行大规模排序操作的场景,可以适当增大sort_buffer_size;而对于内存有限且查询结果集列数据长度差异较大的情况,需要谨慎设置max_length_for_sort_data,以平衡单路排序和双路排序的选择。 - 精简查询语句:在编写查询语句时,尽量减少不必要的列选择,只获取实际业务所需的数据列。这样可以降低数据量,不仅有助于文件排序的效率提升,还能减少网络传输开销和内存占用。
- 避免随机排序:尽量减少使用
ORDER BY RAND()这类导致随机排序的操作,因为它几乎总是会引发大规模的文件排序,尤其是在数据量较大时,会严重影响查询性能。如果确实需要随机获取数据,可以考虑采用其他替代方案,如在应用层进行随机处理或者利用数据库的特定功能(如 MySQL 8.0 中的窗口函数等)来实现类似效果。
通过深入理解 MySQL 中的索引排序和文件排序机制,并依据上述优化建议对数据库结构和查询语句进行合理优化,能够有效地提升数据库查询的性能,为应用系统的高效稳定运行提供坚实的保障。
相关文章:
MySQL 中的排序:索引排序与文件排序
文章目录 MySQL 中的排序:索引排序与文件排序全解析一、引言二、索引排序(一)原理(二)示例 三、文件排序(一)单路排序(二)双路排序(三)归并排序 四…...
深入理解React Hooks:使用useState和useEffect
引言 React Hooks是React 16.8引入的一项强大功能,它使函数组件能够使用状态和其他React特性。本文将深入探讨两个最常用的Hooks:useState和useEffect,并通过实际代码示例展示它们的使用方法。 1. 什么是React Hooks? React Ho…...
AWS codebuild + jenkins + github 实践CI/CD
前文 本文使用 Jenkins 结合 CodeBuild, CodeDeploy 实现 Serverless 的 CI/CD 工作流,用于自动化发布已经部署 lambda 函数。 在 AWS 海外区,CI/CD 工作流可以用 codepipeline 这项产品来方便的实现, CICD 基本概念 持续集成( Continuous…...
Android PMS(Package Manager Service)源码介绍
文章目录 前言一、PMS 启动流程二、APK 安装流程三、APK 卸载流程四、权限管理静态权限动态权限 五、 数据存储与一致性六、 PMS 的安全性策略1、权限检查2、签名认证3、动态权限管理4、应用安装验证5、保护系统目录 七、PMS 调试方法总结 前言 PackageManagerService…...
运维面试整理总结
面试题可以参考:面试题总结 查看系统相关信息 查看系统登陆成功与失败记录 成功:last失败:lastb 查看二进制文件 hexdump查看进程端口或连接 netstat -nltp ss -nltp补充:pidof与lsof命令 pidof [进程名] #根据 进程名 查询进程id ls…...
图数据库 Cypher语言
图数据库 属性图 属性图(Property Graph)概述 属性图是一种广泛用于建模关系数据的图数据结构,它将**顶点(节点)和边(关系)**进行结构化存储,并为它们附加属性以提供丰富的语义信…...
阿里云oss转发上线-实现不出网钓鱼
本地实现阿里云oss转发上线,全部代码在文末,代码存在冗余 实战环境 被钓鱼机器不出网只可访问内部网络包含集团oss 实战思路 若将我们的shellcode文件上传到集团oss上仍无法上线,那么就利用oss做中转使用本地转发进行上线,先发送…...
Spring Boot 3.4.0 发行:革新与突破的里程碑
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
【网络安全】
黑客入侵 什么是黑客入侵? “黑客”是一个外来词,是英语单词hacker的中文音译。最初,“黑客”只是一个褒义词,指的是那些尽力挖掘计算机程序最大潜力的点脑精英,他们讨论软件黑客的技巧和态度,以及共享文化…...
在SQLyog中导入和导出数据库
导入 假如我要导入一个xxx.sql,我就先创建一个叫做xxx的数据库。 然后右键点击导入、执行SQL脚本 选择要导入的数据库文件的位置,点击执行即可 注意: 导入之后记得刷新一下导出 选择你要导出的数据库 右键选择:备份/导出、…...
RabbitMQ简单应用
概念 RabbitMQ 是一种流行的开源消息代理(Message Broker)软件,它实现了高级消息队列协议(AMQP - Advanced Message Queuing Protocol)。RabbitMQ 通过高效的消息传递机制,主要应用于分布式系统中解耦应用…...
使用LUKS对Linux磁盘进行加密
前言 本实验用于日常学习用,如需对存有重要数据的磁盘进行操作,请做好数据备份工作。 此实验只是使用LUKS工具的冰山一角,后续还会有更多功能等待探索。 LUKS(Linux Unified Key Setup)是Linux系统中用于磁盘加密的一…...
戴尔电脑安装centos7系统遇到的问题
1,找不到启动盘(Operation System Loader signature found in SecureBoot exclusion database(‘dbx’).All bootable devices failed secure Boot Verification) 关闭 Secure Boot(推荐): 进入 BIOS/UEFI…...
3.4.SynchronousMethodHandler组件之ResponseHandler
前言 feign发送完请求后, 拿到返回结果, 那么这个返回结果肯定是需要经过框架进一步处理然后再返回到调用者的, 其中ResponseHandler就是用来处理这个返回结果的, 这也是符合正常思维的处理方式, 例如springmvc部分在调用在controller端点前后都会增加扩展点。 从图中可以看得…...
Linux 下进程的状态
操作系统中常见进程状态 在操作系统中有六种常见进程状态: 新建状态: 进程正在被创建. 此时操作系统会为进程分配资源, 如: 内存空间等, 进行初始化就绪状态: 进程已经准备好运行了, 只需要等待被调度, 获取 CPU 资源就可以执行了, 操作系统中可能同时存在多个进程处于就绪状…...
【计算机网络】核心部分复习
目录 交换机 v.s. 路由器OSI七层更实用的TCP/IP四层TCPUDP 交换机 v.s. 路由器 交换机-MAC地址 链接设备和设备 路由器- IP地址 链接局域网和局域网 OSI七层 物理层:传输设备。原始电信号比特流。数据链路层:代表是交换机。物理地址寻址,交…...
Spring Boot开发实战:从入门到构建高效应用
Spring Boot 是 Java 开发者构建微服务、Web 应用和后端服务的首选框架之一。其凭借开箱即用的特性、大量的自动化配置和灵活的扩展性,极大简化了开发流程。本文将以实战为核心,从基础到高级,全面探讨 Spring Boot 的应用开发。 一、Spring B…...
pyshark安装使用,ubuntu:20.04
1.容器创建 命令 docker run -d --name pyshark -v D:\src:/root/share ubuntu:2004 /bin/bash -c "while true;do sleep 1000;done" 用于创建并启动一个新的 Docker 容器。 docker run -d --name pyshark -v D:\src:/root/share ubuntu:2004 /bin/bash -c "w…...
基本功能实现
目录 1、环境搭建 2、按键控制灯&电机 LED 电机 垂直按键(机械按键) 3、串口调试功能 4、定时器延时和定时器中断 5、振动强弱调节 6、万年历 7、五方向按键 1、原理及分析 2、程序设计 1、环境搭建 需求: 搭建一个STM32F411CEU6工程 分析: C / C 宏定义栏…...
《那个让服务器“跳舞”的bug》
在程序的世界里,bug 就像隐藏在暗处的小怪兽,时不时跳出来捣乱。而在我的职业生涯中,有一个bug让我至今难忘,它不仅让项目差点夭折,还让我熬了无数个通宵。这个故事发生在一个风和日丽的下午,我们正在开发一…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
