【MySQL 数据宝典】【索引原理】- 005 一文说明白 OrderBy 优化

mysql索引排序(innoDB引擎) 本文介绍了mysql innodb存储引擎下索引排序规则以及排序优化 阅读详情

MySQL中的两种排序方式

  • 索引排序: 通过有序索引顺序扫描直接返回有序数据
  • 额外排序: 对返回的数据进行文件排序

ORDER BY优化的核心原则: 尽量减少额外的排序,通过索引直接返回有序数据。

一、索引排序

因为索引的结构是B+树,索引中的数据是按照一定顺序进行排列的,所以在排序查询中如果能利用索引,就能避免额外的排序操作。EXPLAIN分析查询时,Extra显示为Using index。
image.png
比如查询条件是 where age = 21 order by name,那么查询过程就是会找到满足 age = 21 的记录,而符合这条的所有记录一定是按照 name 排序的,所以也不需要额外进行排序.

二、额外排序

所有不是通过索引直接返回排序结果的操作都是Filesort排序,也就是说进行了额外的排序操作。EXPLAIN分析查询时,Extra显示为Using filesort。

2.1 按照执行位置划分

2.1.1 Sort_Buffer

MySQL 为每个线程各维护了一块内存区域 sort_buffer ,用于进行排序。sort_buffer 的大小可以通过 sort_buffer_size 来设置。

mysql> show variables like '%sort_buffer_size%';
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| sort_buffer_size        | 262144  |
+-------------------------+---------+

mysql> select 262144 / 1024;
+---------------+
| 262144 / 1024 |
+---------------+
|      256.0000 |
+---------------+

注: sort_Buffer_Size 并不是越大越好,由于是connection级的参数,过大的设置+高并发可能会耗尽系统内存资源。

2.1.2 Sort_Buffer + 临时文件

如果加载的记录字段总长度(可能是全字段也可能是 rowid排序的字段)小于 sort_buffer_size 便使用 sort_buffer 排序;如果超过则使用 sort_buffer + 临时文件进行排序。
临时文件种类:
临时表种类由参数 tmp_table_size 与临时表大小决定,如果内存临时表大小超过 tmp_table_size ,那么就会转成磁盘临时表。因为磁盘临时表在磁盘上,所以使用内存临时表的效率是大于磁盘临时表的。

2.2 按照执行方式划分

执行方式是由 max_length_for_sort_data 参数与用于排序的单条记录字段长度决定的,如果用于排序的单条记录字段长度 <= max_length_for_sort_data ,就使用全字段排序;反之则使用 rowid 排序。

mysql> show variables like 'max_length_for_sort_data';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| max_length_for_sort_data | 1024  |
+--------------------------+-------+

全字段排序

全字段排序就是将查询的所有字段全部加载进来进行排序。

  • 优点:查询快,执行过程简单
  • 缺点:需要的空间大。
select name,age,add from user where addr = '北京' order by name limit 1000; -- addr有索引

image.png
上面查询语句的执行流程:

  1. 初始化 sort_buffer,确定放入 name、age、addr 这3个字段。
  2. 从索引 addr 中找到第一个满足 addr=北京 的主键ID(ID_x)。
  3. 到主键索引中找到 ID_x,取出整行,取 name、addr、age 3个字段的值,存入 sort_buffer。
  4. 从索引 addr 取下一个记录的主键ID。
  5. 重复3、4,直到 addr 值不满足条件。
  6. 对 sort_buffer 中的数据按照 name 做快速排序。
  7. 把排序结果中的前1000行返回给客户端。

rowid 排序

rowid 排序相对于全字段排序,不会把所有字段都放入sort_buffer。所以在sort buffer中进行排序之后还得回表查询。
缺点:会产生更多次数的回表查询,查询可能会慢一些。
优点:所需的空间更小

select name,age,add from user where addr = '北京' order by name limit 1000; -- addr有索引

假设 name、age、addr3个字段定义的总长度为36,而 max_length_for_sort_data = 16,就是单行的长度超了,MySQL认为单行太大,需要换一个算法。
放入 sort_buffer 的字段就会只有要排序的字段 name,和主键 id,那么排序的结果中就少了 addr 和 age,就需要回表了。
image.png
上面查询语句的执行流程:

  1. 初始化 sort_buffer,确定放入2个字段,name 和 id。
  2. 从索引 addr 中找到第一个满足addr=’北京’的主键ID(ID_x)。
  3. 到主键索引中取出整行,把 name、id 这2个字段放入 sort_buffer。
  4. 从索引 addr 取下一个记录的主键ID。
  5. 重复3、4,直到addr值不满足条件。
  6. 对 sort_buffer 中的数据按照 name 做快速排序。
  7. 取排序结果中的前1000行,并按照 id 的值到原表中取出 name、age、addr 3个字段的值返回给客户端。

2.3 总结

  • 如果 MySQL 认为内存足够大,会优先选择全字段排序,把需要的字段都放到 sort_buffer中, 这样排序后就会直接从内存里面返回查询结果了,不用再回到原表去取数据。
  • MySQL 的一个设计思想:如果内存够,就要多利用内存,尽量减少磁盘访问。 对于 InnoDB 表来说,rowid 排序会要求回表多造成磁盘读,因此不会被优先选择。

三、排序优化

添加索引

为 employee表 创建索引

-- 联合索引
ALTER TABLE employee ADD INDEX idx_name_age(NAME,age);

-- 为薪资字段添加索引
ALTER TABLE employee ADD INDEX idx_salary(salary);

查看 employee 表的索引情况

SHOW INDEX FROM employee; 

image.png

场景分析

【生效】 只查询用于排序的索引字段

查询 name, age 两个字段, 并使用 name 与 age 行排序

EXPLAIN SELECT e.name, e.age FROM employee e ORDER BY e.name,e.age;

image.png

【无效】 排序字段在多个索引中

  • 查询 name , salary 字段, 并使用 name 与 salary 排序
EXPLAIN SELECT e.name, e.salary FROM employee e ORDER BY e.name,e.salary;

image.png

【有效】只查询用于排序的索引字段和主键

  • 查询 id , name , 使用 name 排序
EXPLAIN SELECT e.id, e.name FROM employee e ORDER BY e.name;

image.png

【无效】 查询主键之外的没有添加索引的字段

  • 查询 dep_id ,使用 name 进行排序
EXPLAIN SELECT e.dep_id FROM employee e ORDER BY e.name;
EXPLAIN SELECT id, e.dep_id FROM employee e ORDER BY e.name;
EXPLAIN SELECT * FROM employee e ORDER BY e.name;

image.png

【无效】 排序字段顺序与索引列顺序不一致

  • 使用联合索引时, ORDER BY子句也要求, 排序字段顺序和联合索引列顺序匹配。
EXPLAIN SELECT e.name, e.age FROM employee e ORDER BY e.age,e.name;

image.png

【无效】where 条件是 范围查询时

  • 比如 添加一个条件 :  age > 18 ,然后再根据 age 排序.
EXPLAIN SELECT e.name, e.age FROM employee e WHERE e.age > 10 ORDER BY e.age;

image.png

  • 注意: ORDERBY子句不要求必须索引中第一列,没有仍然可以利用索引排序。但是有个前提条件,只有在等值过滤时才可以,范围查询时不可以
EXPLAIN SELECT e.name, e.age FROM employee e WHERE e.age = 18 ORDER BY e.age;

image.png

【无效】升降序不一致,无法利用索引排序

  • ORDER BY排序字段要么全部正序排序,要么全部倒序排序,否则无法利用索引排序。
-- 升序
EXPLAIN SELECT e.name, e.age FROM employee e ORDER BY e.name , e.age ;

-- 降序
EXPLAIN SELECT e.name, e.age FROM employee e ORDER BY e.name DESC, e.age DESC;

image.png

  • name字段升序,age字段降序,索引失效
EXPLAIN SELECT e.name, e.age FROM employee e ORDER BY e.name, e.age DESC;

image.png

Cryptomatte For Nuke的安装 进入官网https://github.com/Psyop/Cryptomatte,下载文件代码。 将Cryptomatte/nuke里的文件内容复制粘贴到 .nuke文件夹内。 在我们复制粘贴的内容中可以看到两个文件。 同时,我们进入nuke的下载目录,打开plugins文件夹,看到和插件中一样python文件——init.py和menu.py。 我们将Cryptomatte里的init.py和menu.py里的python代码复制粘贴到Nuke/plugins下的init... 阅读详情

相关推荐

Keysight ADS新手必看:3分钟搞定TDR模拟的保姆级教程(附差分信号设置技巧)

本文为Keysight ADS新手提供TDR模拟的保姆级教程,详细介绍了从基础环境准备到差分信号设置的全流程。通过内置模板调用、待测器件连接和仿真结果解读,帮助用户快速掌握TDR模拟技术,特别包含差分信号配置技巧,提升信号完整性分析效率。

weixin_30872157的博客 195

索引排序

索引排序 在排序时,若是数据很复杂,对数据的移动显然是费时的。若把数据移动改为指针移动,则减少了操作复杂度。索引排序,也叫地址排序,就是这种排序思想。 索引含义 根据索引的含义不同,索引排序的算法上也主要分为两种。 一、index[i]为array[i]最终在有序序列中的位置。 二、index[i]为位置i上最终应存放元素的下标。即最终元素按array[index[0]]、array[index[1]]……有序。

CCPP Blog 1万+

OFDM调制matlab仿真详细代码

MATLAB仿真代码 % ================================================== % 作者: 肆拾伍 % 时间:11/30 2019 % 版本:V3 % =================OFDM仿真参数说明:================ % % 子载波数 carrier_count ---200 % 总符号数 symbol_count ...

肆拾伍的博客 3万+

排序专题之索引排序

索引排序 和基数排序的 链式法有点相似,下面来看一下一种索引排序方法索引数组s[i]存放的是a[i]数组的原先应该在的数组位置,相当于 a[i]=a[s[i]];下列演示一个该内容的算法:从0---n-1开始遍历,如果索引值和当前位置不符合,就顺着索引链进行循环调整,直到找到等于当前下标值的索引位置为止。每一轮循环所涉及的记录都调整到位,其索引下标都改为所在位置的小比,即满足“索引值等于下标值”,...

薛云飞(Jesse Xue) 5813

WRF移动嵌套结合伏羲模型与CFD(PALM)高精度多尺度降尺度分析研究

WRF移动嵌套(Moving Nesting):动态调整高分辨率嵌套网格位置,追踪天气系统(如台风、强对流系统)以提高局地预报精度。伏羲(Fuxi)模型:国产数值模式,提供对WRF模拟的初始及边界条件优化。CFD(Computational Fluid Dynamics)PALM模型:精细化局地流场、湍流、温度分布。

m0_57411304的博客 1715

ArcGIS天地图矢量化秘籍:用重分类+ArcScan高效提取建筑轮廓线

本文详细介绍了利用ArcGIS重分类和ArcScan技术高效提取天地图建筑轮廓线的半自动化流程。通过动态中断值计算、多级重分类策略和ArcScan高级矢量化技巧,显著提升城市规划中的矢量化效率与精度,适用于中级GIS用户。

weixin_30879169的博客 475

关于在 MySQL 排序中使用索引这件事!

我们来梳理下:只有当索引的顺序和 order by 子句的顺序完全一致,并且所有列的排序方向也都一致的情况下,MySQL 才能通过索引来对结果进行排序,同时,如果是联合索引,order by 子句也需要满足最左匹配原则。可以看到,在这个查询中,优化器将 ta 表作为了第一张表,tc 表作为了第二张表,那么根据前面的结论,如果使用第一个表中的索引排序,就会用到索引排序,第二张表的则用不了,我们来验证一下。如果是第二张表的索引,就没有用到索引排序,如果两张表的索引都用了,也不会使用索引排序。

江南一点雨的专栏 3033

i茅台最新任务python脚本

从固定的 `header_context` 生成HTTP请求头,并加入用户的`userId`、`MT-Token`等动态信息,以模仿真实的请求。- 发送预约请求,提交商品和门店的参数,如 `sessionId`、`shopId`、`itemId` 等。- 定时任务:通过 `cron` 表达式 `0 0 9/21 * * *`,表示每月的9日和21日的0点执行。- `login`:使用验证码进行登录,并返回 `token` 和 `userId`。- 获取北京时间当天0点的时间戳,作为预约请求的时间参数。

三维点云技术探索 982

【索引】数据库索引之顺序索引

聚簇索引的数据和索引存储在一个文件中, 它的叶子节点包含实际的数据记录本身,而不是指向数据记录的指针。这不同于非聚簇索引,非聚簇索引的叶子节点包含指向数据记录位置的指针。

swadian2008的博客 2894

Go游戏服务器开发的一些思考(一):语言层面

Go是比C++更好用的高级语言使用Go作为服务器开发的主语言前,首先需要对Go语言做下定性。在接触Go前,可能给人的印象(至少是我),Go是一门脚本语言。看了 官方文档 ,才知道Go是一门高级语言。与C++相比,它有以下优势: 面向接口的编程没有C++复杂的面向对象语法,如类、继承、多态、虚函数等等。Go中只有结构与接口,从语言层面上,直接指导功能与功能间的解耦。直接且语法简单 提供语言反射机制提供

范安崇的博客 9560

【雷达成像】基于matlab SAR雷达成像仿真【含Matlab源码 3750期】

SAR雷达成像仿真 完整的代码,方可运行;可提供运行操作视频!适合小白!

订阅付费专栏Matlab(奶茶价版),可赠送奶茶价版付费专栏指定代码1份; 1084

Mysql索引两种排序方式分析

最新的 Java 面试题,技术栈涉及 Java 基础、集合、多线程、Mysql、分布式、Spring全家桶、MyBatis、Dubbo、缓存、消息队列、Linux…等等,会持续更新。

qq_42872034的博客 1512

【本地部署实战】LM Studio深度使用指南:从环境搭建到模型调优

LM Studio通过极简的操作流程和强大的生态兼容性,让本地部署大模型成为可能。随着M4芯片的发布和CUDA 12.0的优化,未来本地化AI开发将迎来新的爆发点。建议开发者关注官方Discord社区(https://discord.gg/lmstudio)获取最新模型支持信息。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 8750

MySQL索引原理详解

数据库索引原理、索引失效情况、SQL执行顺序

huangtenglong的博客 2872

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

架构师系列-MYSQL调优(六)- 排序优化

MySQL中的两种排序方式。

dengwei_dw的专栏 1084

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

索引排序顺序

定义索引时,应该考虑索引键列的数据是按升序还是按降序存储。升序是默认设置,保持与 SQL Server 早期版本的兼容性。CREATE INDEX、CREATE TABLE 和 ALTER TABLE 语句的语法在索引和约束中的各列上支持关键字 ASC(升序)和 DESC(降序): 当引用表的查询包含用以指定索引中键列的不同方向的 ORDER BY 子句时,指定键值存储在该索引中的顺序很有用。在

cxzhq2002的杂记 2658

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

mysql(六)多列索引之索引顺序问题

使用索引常见的错误是。

weixin_43994761的博客 2674

【MySQL进阶】索引排序内部逻辑——单路排序和双路排序详解

【MySQL进阶】索引排序内部逻辑——单路排序和双路排序详解

blblccc 2465

MySQL的索引顺序和普通排序的关系到底是什么?一共包含哪些部分?

场景是否利用索引顺序示例代码ORDER BY 与索引完全匹配✅(有 idx_age 索引)ORDER BY 与复合索引部分匹配✅(部分加速)(有 idx_age_salary 索引)ORDER BY 与索引顺序相反❌(索引为 ASC 时无效)ORDER BY 字段无索引❌(无 email 索引)索引顺序 vs 普通排序的本质区别特性索引顺序普通排序数据状态已排序(B+树结构)未排序(需要额外排序)执行效率极快(直接按顺序读取)较慢(涉及内存/磁盘排序)适用场景。

长风破浪会有时的博客 1198

索引原理

索引简述: 索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址,在数据十分庞大的时候,索引可以大大加快查询的速度,这是因为使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据。 我们可以用大白话理解一下: 假如我们一般习惯于使用模糊查询,那么如果在数据量千万级别甚至以上的基础下我们如果不进行优化,那么查询速度会大...

此男子淡漠 1140

采用索引的方法来实现几种经典的排序算法

排序算法

HexDi的博客 1974

索引排序与外排序区别详解

特性索引排序外排序本质“视图”排序“数据”排序动机避免移动数据突破内存限制结果有序的索引/指针有序的新文件有时这两种技术会结合使用。例如,在一个数据库系统中,当你对一个大于内存的表创建索引时,数据库引擎可能会使用外排序算法来对磁盘上的索引条目(这些条目本身就是一种“指针”)进行排序,从而最终构建出一个索引排序所需的有序索引结构。

ITHomeZSL的博客 882

索引与排序

索引与排序排序可能发生2种情况:1: 对于覆盖索引,直接在索引上查询时,就是有顺序的, using index2: 先取出数据,形成临时表做filesort(文件排序,但文件可能在磁盘上,也可能在内存中)我们的争取目标-----取出来的数据本身就是有序的! 利用索引来排序.表中有个index(cat_id, shop_price)联合索引:这里没有用到sort file,因...

weixin_34087503的博客 787

mysql调优-排序

mysql调优-排序优化 第一章、mysql索引排序 文章目录mysql调优-排序优化mysql的两种排序方式方式A:filesort(文件排序)双路查找原理:单路查找原理方式B:index(索引排序)原理一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 mysql的两种排序方式 方式A:filesort(文件排序) 双路查找 原理: 单路查找 原理 方式B:index(索引排序) 原理 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,

特别剑的博客 1957
上一篇: 【MySQL 数据宝典】【索引原理】- 004 优化示例-join & in &exist
下一篇: 【MySQL 数据宝典】【索引原理】- 006 慢查询日志分析&优化
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值