MySQL——优化ORDER BY语句
本篇文章我们将了解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——索引优化实战
数据库索引背后的数据结构
是什么影响了数据库索引选型?
MySQL——优化ORDER BY语句相关推荐
- mysql order by 语句_Mysql优化order by语句的方法详解
本篇文章我们将了解ORDER BY语句的优化,在此之前,你需要对索引有基本的了解,不了解的老少爷们可以先看一下我之前写过的索引相关文章.现在让我们开始吧. MySQL中的两种排序方式 1.通过有序索引 ...
- mysql order by 多个字段 索引_mysql 索引优化order by 语句
MySql创建索引时支持ASC或DESC排序. 下面举例 创建表时同时创建索引降序排序(sname 字段上普通索引降序) create table tbl1 ( id int unique, snam ...
- MySQL中order by语句的实现原理以及优化手段
相信很多人在面试过程中,总被问到有没有 SQL 调优经验,对于工作经验年限较少的求职者,通常都是在面试之前从网上百度一些答案,提前背熟,然后面试的时候直接将提前背好的答案说出来.笔者作为一名菜鸟,在刚 ...
- 【重要】MySQL中order by语句的实现原理以及优化手段
写在前面 filesort排序算法参考 :https://blog.csdn.net/lijingkuan/article/details/70341176 双路排序:是首先根据相应的条件取出相应的排 ...
- SQL优化—— 优化order by语句 || Filesort 的优化
两种排序方式 1). 第一种是通过对返回数据进行排序,也就是通常说的 filesort 排序,所有不是通过索引直接返回排序结果的排序都叫 FileSort 排序. 2). 第二种通过有序索引顺序扫描直 ...
- MySQL 优化 —— ORDER BY 优化
引言 本文翻译自MySQL 官网:ORDER BY Optimization,MySQL 版本:5.7. 这一部分描述了MySQL何时会使用索引来满足order by子句,filesort 操作会在索 ...
- 优化order by语句
mysql可以通过查看sql执行计划知道其排序方式有两种 using filesort 和 using index 第一种是通过对返回数据进行排序,也就是通常说的filesort排序,所有不是通过索引 ...
- 简单mysql优化_mysql常见语句的简单优化策略
常见sql优化方法 (1)优化insert语句 大批量插入数据: 对于Myisam类型的表,可以通过以下方式快速的导入大量的数据. ALTER TABLE tblname DISABLE KEYS; ...
- mysql优化or_mysql or语句的优化
在某些情况下,or条件可以避免全表扫描的. 1 .where 语句里面如果带有or条件,myisam表能用到索引, innodb不行. 1)myisam表: CREATE TABLE IF NOT E ...
最新文章
- 双时隙的工作原理_工业内窥镜的原理是什么?有哪些测量方法
- 自动执行任务_中小企业如何做运维自动化?
- java动态分区分配_动态分区分配--最先适应分配算法
- Java并发环境下,先操作数据库还是先操作缓存?
- R语言colorRampPalette函数-创建颜色梯度(渐变色)
- xp系统怎么看计算机内存条,XP环境下怎么查看虚拟内存?XP系统虚拟内存过低怎么设置?...
- 4.widows对象
- 大数据之oracle:next_day函数
- 【官方文档】Fluent Bit 数据管道之过滤插件(Parser)
- PCIe“拍了拍”PCI- PCI和PCIe发展历史
- 二进制调色器程序管理
- ubuntu 内存占用过高导致卡死 解决办法
- 圣诞邮件怎么写?收藏住~
- 操作系统的名字的读音
- 使用visio如何快速生成一个网格状图案,文档技巧!
- python基础5-模块定义、导入方法、import本质、time和datetime、random、os、sys、shutil、shelve、xml、ConfigParser、hashlib、re
- 【Leetcode-算法】844. 比较含退格的字符串(C++)
- fmdb和mysql的区别_FMDB介绍和使用
- html类选择器和id选择器,类和ID选择器的区别
- Swift语言中的控制语句和函数
热门文章
- Linux资源监控工具
- 【总结】大规模数据(300万条)测试时,需要注意的问题。
- 【HDFS】HDFS操作命令
- vs code 问题:preLaunchTask“build”已终止,退出代码为 1。解决办法
- VueTreeselect出现unknown解决方法
- Android studio R文件丢失或错误解决方法
- VS code中使用code runner遇到两例问题之解决:1.输出乱码,2运行无响应(输出)
- Oracle数据库中文乱码问题解决
- 启动tomcat时 错误: 代理抛出异常 : java.rmi.server.ExportException: Port already in use: 1099的解决办法
- 解决chrome浏览器adobe flash player不是最新版本亲测可用的方法