mysql 排序速度_MySQL排序速度慢而且可能不稳定
一、具体现象
有一个功能,按照算法得出的权重值,分页展示一批列表数据,权重值越大越靠前。研发同学反馈查询速度慢且排序不稳定。
排序不稳定的具体现象,有不少记录存在相同权重值,某条记录(假设id=100)第一页出现了,翻到第二页可能还有它(采用的limit控制哪一页)。
第1页数据
第2页数据
一个主表A,左连接两个表B、C,根据C的权重字段排序。具体SQL如下
二、问题分析
查看SQL语句的执行计划(EXPLAIN),发现有Using filesort的字样。
赶紧搜索一下MySQL说明文档,第一条是排序优化
文档中有这么一句话“如果索引不能满足ORDERBY子句,MySQL将执行文件排序(filesort)操作,读取数据行并对其进行排序。文件排序构成查询执行中的额外排序阶段。”
显然,利用索引实现有序,比采用filesort更高效。filesort并不一定都通过磁盘排序,数据量不大的时候是在内存里完成。速度不够快的原因找到了。
filesort的时候可能在内存中出现堆排序列或快速排序两种方式,具体使用哪一种排序方式是优化器决定的,基本原则如下
快速排序算法:大量排序
堆排序算法:排序量不大
快速排序和堆排序是不稳定的排序算法,对于重复值不能保证顺序。Order by排序不稳定的原因也定位到了
了解一下filesort的原理
(1)根据表的索引或者全表扫描,读取所有满足条件的记录。
(2)对于每一行,存储一对值到缓冲区(排序列,行记录指针),一个是排序的索引列的值,即order by用到的列值,和指向该行数据的行指针,缓冲区的大小为sort_buffer_size大小。
(3)当缓冲区满后,运行一个快速排序(qsort)来将缓冲区中数据排序,并将排序完的数据存储到一个临时文件,并保存一个存储块的指针,当然如果缓冲区不满,则不会重建临时文件了。
(4)重复以上步骤,直到将所有行读完,并建立相应的有序的临时文件。
(5)对块级进行排序,这个类似归并排序算法,只通过两个临时文件的指针来不断交换数据,最终达到两个文件,都是有序的。
(6)重复5直到所有的数据都排序完毕。
(7)采取顺序读的方式,将每行数据读入内存(这里读取数据时并不是一行一行读),并取出数据传到客户端,读取缓存大小由read_rnd_buffer_size来指定。
三、怎么优化
1、利用索引达到排序目的(针对例子的优化)
针对文章开始的例子,优化原则是Use of Indexes to Satisfy ORDER BY(让ORDER BY用上索引),即提升查询效率,又保证稳定性(索引B+树叶子结点的顺序是唯一且一定的)
MySQL的文档列出若干具体的case,把最主要整理出来如下。
MySQL文档中有这么一句话 “该查询连接了许多表,并且ORDER BY中的列并非全部来自用于检索行的第一个非恒定表。”,满足这类型的SQL也不能利用索引排序。这就是文章开头的例子。另外,使用别名,如果跟表的列名冲突可能导致索引排序失效。
看到有些文章写到下面这条语句ORDER BY不能利用索引
这个说法显然与MySQL官方文档不一致。我觉得,这个语句能不能使用索引,跟数据库引擎根据开销决定是否检索的阶段使用索引有关。
2、优化filesort
如果确实没办法利用索引,可以想办法优化filesort排序。
如果结果集太大内存装不下,filesort将根据需要使用临时磁盘文件。磁盘io速度你懂的!MySQL官方建议可以调大排序缓存参数sort_buffer_size,MySQL 8.0还对缓存利用率做了优化,调大一点也不浪费。以前版本的MySQL可以求助DBA。
可以这样优化的典型SQL 语句如下
3、其他
有些ORDER BY甚至连filesort都不能用,对这类优化感觉有点超纲了,把原文贴一下
“对于不使用filesort的慢排序查询,请尝试将“max_length_for_sort_data”参数调低到适合触发filesort的值(此参数的值设置得过高的一个表现是磁盘IO高和CPU负载低)”
四、实际效果
文章开头例子的一种场景,我们巧妙利用了索引排序,达到很好的效果。
另外一个场景仍然使用filesort的排序方式
当然更好的做法是接入ES之类的搜索引擎
长按关注V社北京
测试丨技术丨面试丨DevOps
关注V社北京,关注测试,添加巨蜥小程序获取全量精品技术文章
关注我
mysql 排序速度_MySQL排序速度慢而且可能不稳定相关推荐
- mysql排序优化_Mysql 排序优化
为了优化SQL语句的排序性能,最好的情况是避免排序,合理利用索引是一个不错的方法.因为索引本身也是有序的,如果在需要排序的字段上面建立了合适的索引,那么就可以跳过排序的过程,提高SQL的查询速度.下面 ...
- mysql数据排序指令_MySQL 排序 | 菜鸟教程
MySQL 排序 我们知道从 MySQL 表中使用 SQL SELECT 语句来读取数据. 如果我们需要对读取的数据进行排序,我们就可以使用 MySQL 的 ORDER BY 子句来设定你想按哪个字段 ...
- mysql 内存表 速度_mysql查询速度。为什么用内存表查询tmp表比直接选择慢?
我有点困惑这种MySQL行为. 一个带有ORDER BY子句的查询将创建tmp表(如show profile所示),并且运行速度更快,即使没有order with with的相同查询也不会创建tmp ...
- mysql 时间排序查询_Mysql排序查询
/* 语法:select 查询列表 from 表 [where 筛选条件] order by 排序序列 [asc/desc] */ SELECT * FROM employees ORDER BY s ...
- mysql索引排序算法_MySQL中利用索引对数据进行排序的基础教程
MySQL中,有两种方式生成有序结果集:一是使用filesort,二是按索引顺序扫描.利用索引进行排序操作是非常快的,而且可以利用同一索引同时进行查找和排序操作.当索引的顺序与ORDER BY中的列顺 ...
- mysql默认字符集和排序_MySQL字符集和排序规则
MySQL在创建数据库是,需要设置数据库的字符集和排序规则,如图所示: 我觉得这里有必要解释下字符集和排序规则这两个概念. 字符集 说到字符集,需要先提下字符.字符集和字符编码这几个词的含义. 字符( ...
- mysql 排序字段索引吗_Mysql 排序优化与索引使用(转)
为了优化SQL语句的排序性能,最好的情况是避免排序,合理利用索引是一个不错的方法.因为索引本身也是有序的,如果在需要排序的字段上面建立了合适的索引,那么就可以跳过排序的过程,提高SQL的查询速度.下面 ...
- mysql怎么排序检索_MySQL 2 SQL数据使用(检索、排序、过滤:SELECT/FROM/LIMIT/ORDER BY/DESC/WHERE/AND/OR/IN/NOT)...
.空格被忽略,可以用一或多个空格分开指令. 检索单个列: SELECT 列名 FROM 表名: 检索多个列: 当心逗号 SELECT 列1,列2,列3 FROM 表: 检索所有列:(*)通配符 S ...
- java实现八种排序算法并测试速度(详细)
算法代码: /*** Created by CLY on 2017/3/17.*/ package pers.cly.sorting; /*** 排序工具类,里面包含各种排序方法*/ public c ...
最新文章
- UVa11022 String Factoring(kmp+dp)
- 【转】Linux添加/删除用户和用户组
- Android 中input event的分析
- hc05与单片机连接图_基于proteus的51单片机开发实例(13)-LED指示那个按键被按下
- 拉取远程分支_git clone切换分支步骤,代理设置,作者信息设置
- 微服务架构最强讲解,通俗易懂,写得太好了!
- Python多线程及其使用方法
- 这个 bug 可劫持同一 WiFi 网络上所有的安卓版火狐移动浏览器
- 数据库连接报错2013-lost connection to mysql server at ‘reading initial communication packet’ system error:0
- ARM给服务器厂商更多创新机会
- nod32/ESET下載及更新
- python 区块链_如何用Python快速实现区块链?
- 队列基本操作模拟打印机任务管理
- HTTP协议和Servlet技术
- 闲置服务器如何利用起来赚点零花钱
- C++ 利用 windbg + dump + map + cod 文件分析 crash 原因
- 《互联网时代》第四集 再构
- sw运行很卡怎么办_怎样才能提高Solidworks的运行速度/SW运行慢怎么办?
- 清华计算机系超算团队,清华学生超算团队获得国际大学生超级计算机竞赛总冠军...
- Python 的 pytest 测试框架
热门文章
- UI设计干货素材|动态交互插画模板
- python 条形图 负值_Python处理JSON数据并生成条形图
- poj 1006 java_POJ 1006 Java:中国剩余定理
- ++i和i++哪个效率更高
- CVE-2022-0847-DirtyPipe-Exploit
- 实时Linux内核调度器 | Real-Time Linux Kernel Scheduler
- Linux内存管理:内存寻址之分段机制与分页机制
- CRC32(Cyclic Redundancy Check)循环冗余校验:推导
- 物理层上/下行每个功能块需要的信息
- 计算机容量单位比T,容量单位.比G大是T.比T大是E.比E大是什么?