本篇文章我们将了解ORDER BY语句的优化,在此之前,你需要对索引有基本的了解,不了解的朋友们可以先看一下我之前写过的索引相关文章。现在让我们开始吧。

MySQL中的两种排序方式

1.通过有序索引顺序扫描直接返回有序数据

因为索引的结构是B+树,索引中的数据是按照一定顺序进行排列的,所以在排序查询中如果能利用索引,就能避免额外的排序操作。EXPLAIN分析查询时,Extra显示为Using index。

2.Filesort排序,对返回的数据进行排序

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

ORDER BY优化的核心原则

尽量减少额外的排序,通过索引直接返回有序数据。

ORDER BY优化实战

用于实验的customer表的索引情况:

首先要注意:

MySQL一次查询只能使用一个索引,如果要对多个字段使用索引,建立复合索引。

ORDER BY优化

1.查询的字段,应该只包含此次查询使用的索引字段和主键,其余的非索引字段和索引字段作为查询字段则不会使用索引。

只查询用于排序的索引字段,可以利用索引排序:

explain select store_id,email from customer order by store_id,email;

但是要注意,排序字段在多个索引中,无法使用索引排序,查询一次只能使用一个索引:

explain select store_id,email,last_name from customer order by store_id,email,last_name;

只查询用于排序的索引字段和主键,可以利用索引排序:

画外音:MySQL默认的InnoDB引擎在物理上采用聚集索引这种方式,按主键进行搜索,所以InnoDB引擎要求表必须有主键,即使没有显式指定主键,InnoDB引擎也会生成唯一的隐式主键,也就是说索引中必定有主键。

explain select customer_id,store_id,email from customer order by store_id,email;

查询用于排序的索引字段和主键之外的字段,不会利用索引排序:

explain select store_id,email,last_name from customer order by store_id,email;

explain select * from customer order by store_id,email;

WHERE + ORDER BY 优化

1.排序字段在多个索引中,无法利用索引排序

排序字段在多个索引(不在同一个索引)中,无法利用索引排序:

explain select * from customer where last_name='swj' order by last_name,store_id;

画外音:当排序字段不在同一个索引时,无法满足在一颗B+树中完成排序,必须再进行一次额外的排序

排序字段在一个索引中,并且WHERE条件和ORDER BY使用相同的索引,可以利用索引排序:

explain select * from customer where last_name='swj' order by last_name;

当然组合索引也可以利用索引排序:

注意字段store_id,email在一个组合索引中

explain select * from customer where store_id = 5 order by store_id,email;

2.排序字段顺序与索引列顺序不一致,无法利用索引排序

画外音:这条是针对组合索引而言的,我们都知道使用组合索引必要要遵循最左原则,WHERE子句必须有索引中第一列,虽然ORDER BY子句没有这个要求,但是也要求排序字段顺序和组合索引列顺序匹配。我们平常在使用组合索引的时候,一定要养成按照组合索引列顺序书写的好习惯。

排序字段顺序与索引列顺序不一致,无法利用索引排序:

explain select * from customer where store_id > 5 order by email,store_id;

应该确保排序字段顺序与索引列顺序一致,这样可以利用索引排序:

explain select * from customer where store_id > 5 order by store_id,email;

ORDER BY子句不要求必须索引中第一列,没有仍然可以利用索引排序。但是有个前提条件,只有在等值过滤时才可以,范围查询时不可以

explain select * from customer where store_id = 5 order by email;

explain select * from customer where store_id > 5 order by email;

画外音:

其原因其实也很简单,范围查询时,第一列a肯定是排序好的(默认是升序),而第二个字段b其实就不是排序的了。但是如果a字段有相同的值时,那么b字段就是排序的了。所以如果是范围查询,就只能对b做一次额外的排序。

3.升降序不一致,无法利用索引排序

ORDER BY排序字段要么全部正序排序,要么全部倒序排序,否则无法利用索引排序。

explain select * from customer where store_id > 5 order by store_id,email;

explain select * from customer where store_id > 5 order by store_id desc,email desc;

explain select * from customer where store_id > 5 order by store_id desc,email asc;

总结:

上面的优化其实可以汇总为:WHERE条件和ORDER BY使用相同的索引,并且ORDER BY的顺序和索引顺序相同,并且ORDER BY的字段都是升序或者降序。否则肯定需要额外的排序操作,就会出现Filesort。

Filesort优化

通过创建合适的索引能够减少Filesort的出现,但是在某些情况下,无法完全让Filesort消失,此时只能想办法加快Filesort的操作。

Filesort的两种排序算法:

1.两次扫描算法

首先根据条件取出排序字段和行指针信息,之后在排序区sort buffer中排序。这种排序算法需要访问两次数据,第一次获取排序字段和行指针信息,第二次根据行指针获取记录,第二次读取操作可能会导致大量随即I/O操作。优点是排序的时候内存开销较小。

2.一次扫描算法

一次性取出满足条件的行的所有字段,然后在排序区sort buffer中排序后直接输出结果集。排序的时候内存开销比较大,但是排序效率比两次扫描算法要高。

根据两种排序算法的特性,适当加大系统变量max_length_for_sort_data的值,能够让MySQL选择更优化的Filesort排序算法。并且在书写SQL语句时,只使用需要的字段,而不是SELECT * 所有的字段,这样可以减少排序区的使用,提高SQL性能。

参考

《深入浅出MySQL》

推荐阅读

MySQL——通过EXPLAIN分析SQL的执行计划

MySQL——索引基础

MySQL——索引优化实战

数据库索引背后的数据结构

是什么影响了数据库索引选型?

作者:CoderFocus
微信公众号:


MySQL——优化ORDER BY语句相关推荐

  1. mysql order by 语句_Mysql优化order by语句的方法详解

    本篇文章我们将了解ORDER BY语句的优化,在此之前,你需要对索引有基本的了解,不了解的老少爷们可以先看一下我之前写过的索引相关文章.现在让我们开始吧. MySQL中的两种排序方式 1.通过有序索引 ...

  2. mysql order by 多个字段 索引_mysql 索引优化order by 语句

    MySql创建索引时支持ASC或DESC排序. 下面举例 创建表时同时创建索引降序排序(sname 字段上普通索引降序) create table tbl1 ( id int unique, snam ...

  3. MySQL中order by语句的实现原理以及优化手段

    相信很多人在面试过程中,总被问到有没有 SQL 调优经验,对于工作经验年限较少的求职者,通常都是在面试之前从网上百度一些答案,提前背熟,然后面试的时候直接将提前背好的答案说出来.笔者作为一名菜鸟,在刚 ...

  4. 【重要】MySQL中order by语句的实现原理以及优化手段

    写在前面 filesort排序算法参考 :https://blog.csdn.net/lijingkuan/article/details/70341176 双路排序:是首先根据相应的条件取出相应的排 ...

  5. SQL优化—— 优化order by语句 || Filesort 的优化

    两种排序方式 1). 第一种是通过对返回数据进行排序,也就是通常说的 filesort 排序,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序. 2). 第二种通过有序索引顺序扫描直 ...

  6. MySQL 优化 —— ORDER BY 优化

    引言 本文翻译自MySQL 官网:ORDER BY Optimization,MySQL 版本:5.7. 这一部分描述了MySQL何时会使用索引来满足order by子句,filesort 操作会在索 ...

  7. 优化order by语句

    mysql可以通过查看sql执行计划知道其排序方式有两种 using filesort 和 using index 第一种是通过对返回数据进行排序,也就是通常说的filesort排序,所有不是通过索引 ...

  8. 简单mysql优化_mysql常见语句的简单优化策略

    常见sql优化方法 (1)优化insert语句 大批量插入数据: 对于Myisam类型的表,可以通过以下方式快速的导入大量的数据. ALTER TABLE tblname DISABLE KEYS; ...

  9. mysql优化or_mysql or语句的优化

    在某些情况下,or条件可以避免全表扫描的. 1 .where 语句里面如果带有or条件,myisam表能用到索引, innodb不行. 1)myisam表: CREATE TABLE IF NOT E ...

最新文章

  1. 双时隙的工作原理_工业内窥镜的原理是什么?有哪些测量方法
  2. 自动执行任务_中小企业如何做运维自动化?
  3. java动态分区分配_动态分区分配--最先适应分配算法
  4. Java并发环境下,先操作数据库还是先操作缓存?
  5. R语言colorRampPalette函数-创建颜色梯度(渐变色)
  6. xp系统怎么看计算机内存条,XP环境下怎么查看虚拟内存?XP系统虚拟内存过低怎么设置?...
  7. 4.widows对象
  8. 大数据之oracle:next_day函数
  9. 【官方文档】Fluent Bit 数据管道之过滤插件(Parser)
  10. PCIe“拍了拍”PCI- PCI和PCIe发展历史
  11. 二进制调色器程序管理
  12. ubuntu 内存占用过高导致卡死 解决办法
  13. 圣诞邮件怎么写?收藏住~
  14. 操作系统的名字的读音
  15. 使用visio如何快速生成一个网格状图案,文档技巧!
  16. python基础5-模块定义、导入方法、import本质、time和datetime、random、os、sys、shutil、shelve、xml、ConfigParser、hashlib、re
  17. 【Leetcode-算法】844. 比较含退格的字符串(C++)
  18. fmdb和mysql的区别_FMDB介绍和使用
  19. html类选择器和id选择器,类和ID选择器的区别
  20. Swift语言中的控制语句和函数

热门文章

  1. Linux资源监控工具
  2. 【总结】大规模数据(300万条)测试时,需要注意的问题。
  3. 【HDFS】HDFS操作命令
  4. vs code 问题:preLaunchTask“build”已终止,退出代码为 1。解决办法
  5. VueTreeselect出现unknown解决方法
  6. Android studio R文件丢失或错误解决方法
  7. VS code中使用code runner遇到两例问题之解决:1.输出乱码,2运行无响应(输出)
  8. Oracle数据库中文乱码问题解决
  9. 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法
  10. 解决chrome浏览器adobe flash player不是最新版本亲测可用的方法