一、具体现象

有一个功能,按照算法得出的权重值,分页展示一批列表数据,权重值越大越靠前。研发同学反馈查询速度慢且排序不稳定。

排序不稳定的具体现象,有不少记录存在相同权重值,某条记录(假设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排序速度慢而且可能不稳定相关推荐

  1. mysql排序优化_Mysql 排序优化

    为了优化SQL语句的排序性能,最好的情况是避免排序,合理利用索引是一个不错的方法.因为索引本身也是有序的,如果在需要排序的字段上面建立了合适的索引,那么就可以跳过排序的过程,提高SQL的查询速度.下面 ...

  2. mysql数据排序指令_MySQL 排序 | 菜鸟教程

    MySQL 排序 我们知道从 MySQL 表中使用 SQL SELECT 语句来读取数据. 如果我们需要对读取的数据进行排序,我们就可以使用 MySQL 的 ORDER BY 子句来设定你想按哪个字段 ...

  3. mysql 内存表 速度_mysql查询速度。为什么用内存表查询tmp表比直接选择慢?

    我有点困惑这种MySQL行为. 一个带有ORDER BY子句的查询将创建tmp表(如show profile所示),并且运行速度更快,即使没有order with with的相同查询也不会创建tmp ...

  4. mysql 时间排序查询_Mysql排序查询

    /* 语法:select 查询列表 from 表 [where 筛选条件] order by 排序序列 [asc/desc] */ SELECT * FROM employees ORDER BY s ...

  5. mysql索引排序算法_MySQL中利用索引对数据进行排序的基础教程

    MySQL中,有两种方式生成有序结果集:一是使用filesort,二是按索引顺序扫描.利用索引进行排序操作是非常快的,而且可以利用同一索引同时进行查找和排序操作.当索引的顺序与ORDER BY中的列顺 ...

  6. mysql默认字符集和排序_MySQL字符集和排序规则

    MySQL在创建数据库是,需要设置数据库的字符集和排序规则,如图所示: 我觉得这里有必要解释下字符集和排序规则这两个概念. 字符集 说到字符集,需要先提下字符.字符集和字符编码这几个词的含义. 字符( ...

  7. mysql 排序字段索引吗_Mysql 排序优化与索引使用(转)

    为了优化SQL语句的排序性能,最好的情况是避免排序,合理利用索引是一个不错的方法.因为索引本身也是有序的,如果在需要排序的字段上面建立了合适的索引,那么就可以跳过排序的过程,提高SQL的查询速度.下面 ...

  8. mysql怎么排序检索_MySQL 2 SQL数据使用(检索、排序、过滤:SELECT/FROM/LIMIT/ORDER BY/DESC/WHERE/AND/OR/IN/NOT)...

    .空格被忽略,可以用一或多个空格分开指令. 检索单个列: SELECT 列名  FROM 表名: 检索多个列: 当心逗号 SELECT 列1,列2,列3  FROM 表: 检索所有列:(*)通配符 S ...

  9. java实现八种排序算法并测试速度(详细)

    算法代码: /*** Created by CLY on 2017/3/17.*/ package pers.cly.sorting; /*** 排序工具类,里面包含各种排序方法*/ public c ...

最新文章

  1. VI常用使用命令 为初次接触VI 的兄弟们献微利
  2. 面试:URI中的 “//” 有什么用?
  3. SpringBoot中通过ConfigurationProperties注解的方式读取application.yml中配置的属性值
  4. SAP Spartacus 3.0 的一些变化
  5. AngularJS:表达式
  6. java aqs详解_Java AQS底层原理解析
  7. java基础 最重要的部分_Java基础(1)最基础的部分
  8. JSF 源代码赏析之Lifecycle
  9. Django模板层:DTL模板渲染-变量
  10. 汽车行业要变天?数据告诉你,为什么说合资车企正在走向末路
  11. Gulp解决发布线上文件(CSS和JS)缓存问题
  12. 人工智能产品经理工作流程
  13. 浏览器兼容性测试及常见问题
  14. Java+阿里云手机验证码发送和验证
  15. spring boot 三种类型事物实现说明
  16. git merge --no-ff 和git merge --squash的区别
  17. 黑客武库升级DDoS电磁炮:威力已不止瘫痪美国半张互联网
  18. 跨行取款手续费上调 广东建行农行每笔涨至4元
  19. 文件复制软件评测:FastCopy、TeraCopy、ExtremeCopy、Supercopier
  20. ubuntu20.04卸载cuda11.4重装cuda11.0

热门文章

  1. 知云文献翻译打不开_比有道更好用的英文文献阅读翻译神器免费啦
  2. 感恩节活动促销海报模板,摆好借势感恩节的姿势
  3. 配色方案|平板羽毛集,为你的下个作品做安排
  4. UI设计干货素材|滑动动效设计模板
  5. qq动态页面变方格_腾讯QQ音乐9.7.5正式版更新:「歌手主页个人主页」界面全新改版...
  6. DW —— 简易计算器 (JavaScript)
  7. lambda函数以及对 items.sort(key = lambda y:y[1], reverse = True) 的理解。
  8. Docker 教程、架构、Linux下的安装
  9. 同济大学转计算机专业绩点,关于同济大学研究生成绩计算方法的说明
  10. python操作系统课程设计_操作系统课程设计.pdf