前言

在mysql中满足order by的处理方式有两种:

  • 让索引满足排序,即扫描有序索引然后再找到对应的行结果,这样结果即是有序;
  • 使用索引查询出结果或者扫描表得到结果然后使用filesort排序;

filesort排序:是针结果在内存中进行排序,如果待排结果较大,mysql可能会产生临时文件输入输出到磁盘。

所以order by的优化思路

  1. 优先使用索引满足排序;
  2. 如果实在满足不了,再优化filesort排序;

使用索引满足order by规律总结

一般where子句的条件查询,大部分条件查询都会使用索引,如果这时加上order by索引生效,只要通过扫描索引即可完成排序,避免了额外的filesort的开销。

In some cases, MySQL may use an index to satisfy an ORDER BY clause and avoid the extra sorting involved in performing a filesort operation.

mysql官方手册描述:

在一些情况下,mysql可能会使用索引满足order by子句,从而避免了使用filesort操作进行的额外排序。

让order by使用索引进行排序时,并不一定需要order by子句中的列完全匹配索引,只要索引中未使用的部分和除了order by列的额外列都在where子句中作为常量匹配,order by仍然可能会使用索引实现排序。

在order by是否使用索引进行排序,都得依赖优化器决定使用索引是否比不使用索引更加高效

下面就总结下order by使用索引排序的几种情况:

  • 如果select的结果是索引列的一部分(即覆盖索引),且order by按照索引的列进行排序,这种情况会扫描整个索引作为返回结果且都不用查询行,同时也使用索引进行排序。如:
create index idx_id_name on table_name (id, name);

// 因为id,name组成联合索引——已经有序,只要扫描整个idx_id_name,获取name即是有序
select name from table_name order by id;

但是这样就会使用文件排序:

// 虽然这里会使用覆盖索引,但是mysql会对查询出的结果做文件排序
// 因为扫描索引idx_id_name,得出的id不一定是按照name有序
// idx_id_name只能保证对id是有序
select id from table_name order by name;
  • 按照完整索引排序,查询所有表行。如:
create index idx_name on table_name (name);
select * from order by name;

以上情况理论上按照使用索引实现排序。但是查询结果包含了其他的非索引列,所以优化器会抉择扫描整个有序索引然后再按需查找所有行是不是比扫描总个表使用filesort哪种方式更廉价。

  • 使用索引一部分列作为where条件常量,另一个部分列作为order by排序,查询所有行。如:
// id,name组成联合索引,在id值为常量的索引中是按照name排序
create index idx_id_name on talbe_name (id, name); select * from where id = constant order by name;

因为这里id是常量,所以按照where条件按照索引idx_id_name查找出的匹配结果行肯定在name上有序。这里影响是否使用索引满足排序的因素在于优化器判断按照id在扫描idx_id_name是比表扫描更廉价。

从以上的几种情况中可以看出两种影响是否使用索引完成排序的因素:

  1. 使用扫描索引找出匹配的结果行是否比全表扫描找出结果带来更大的性能收益。如果用来全表扫描,那么肯定不会使用filesort;

  2. order by排序的列和where的条件的列索引使用上是否契合。如果按照where条件中索引匹配找到的结果,刚好就是按照order by排序的那么,索引查找过程也就完成了order by过程;如果不契合,即是使用了索引找到了匹配结果,任然需要filesort阶段完成排序。如果是单列索引,那么where需要和order by列上保持一致,如果是联合索引,where条件中使用索引列前缀部分,order by使用后半部分;

下面再看一些索引不满足order by的情况

  • order by中使用了不同的索引进行排序
SELECT * FROM t1 ORDER BY key1, key2;
  • 混合使用不同的顺序
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
  • 用于检索结果行的索引和order by索引不是一个
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;

使用filesort满足order by

If an index cannot be used to satisfy an ORDER BY clause, MySQL performs a filesort operation that reads table rows and sorts them. A filesort constitutes an extra sorting phase in query execution.

如果索引不能满足order by,mysql将会执行filesort操作。filesort操作是读取表行,然后在排序它们。在查询中filesort构成了一个额外的排序阶段。

To obtain memory for filesort operations, the optimizer allocates a fixed amount of sort_buffer_size bytes up front. Individual sessions can change the session value of this variable as desired to avoid execessive memory use, or to allocate more memory as necessary.

为了能够执行filesort操作,优化器需要提前分配固定数量的内存,每个大小由sort_buffer_size参数决定。

A filesort operation uses temporary disk files as necessary if the result set is too large to fit in memory.

当结果集太大不能完全放入内存时,filesort操作会使用零时的磁盘文件进行换入换出。

filesort调优策略:

  • 增大sort_buffer_size值,让其足够放下结果集,以便在内存中完成filesort;
  • 增大read_rnd_buffer_size,以便更多行被一次读出;

判断order by使用了哪种方式

With EXPLAIN (see Section 8.8.1, “Optimizing Queries with EXPLAIN”), you can check whether MySQL can use indexes to resolve an ORDER BY clause:

  • If the Extra column of EXPLAIN output does not contain Using filesort, the index is used and a filesort is not performed.
  • If the Extra column of EXPLAIN output contains Using filesort, the index is not used and a filesort is performed.

使用explain,可以检测mysql使用了索引还是是用filesort完成order by:

  • 如果explain的extra中有using filesort,那么表示使用了filesort;
  • 如果没有filesort,表示使用了index;

总结

order by优化的步骤:

  1. 尽量让index方式完成order by:如何where和order by相同列则使用单索引列;如果不同使用联合索引;
  2. 无法使用时,对filesort方式进行调优;
参考

ORDER BY Optimization

Mysql order by与limit混用陷阱

mysql 大数据量分页优化

Mysql序列(七)—— order by优化的更多相关文章

  1. Mysql查询优化汇总 order by优化例子,group by优化例子,limit优化例子,优化建议

    Mysql查询优化汇总 order by优化例子,group by优化例子,limit优化例子,优化建议 索引 索引是一种存储引擎快速查询记录的一种数据结构. 注意 MYSQL一次查询只能使用一个索引 ...

  2. MySql学习(七) —— 查询性能优化 深入理解MySql如何执行查询

    本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...

  3. MySQL性能优化,MySQL索引优化,order by优化,explain优化

    前言 今天我们来讲讲如何优化MySQL的性能,主要从索引方面优化.下期文章讲讲MySQL慢查询日志,我们是依据慢查询日志来判断哪条SQL语句有问题,然后在进行优化,敬请期待MySQL慢查询日志篇 建表 ...

  4. Mysql group by,order by,dinstict优化

    1.order by优化 2.group by优化 3.Dinstinct 优化 1.order by优化 实现方式: 1. 根据索引字段排序,利用索引取出的数据已经是排好序的,直接返回给客户端: 2 ...

  5. mysql实战优化之六:Order by优化 sql优化、索引优化

    在MySQL中的ORDER BY有两种排序实现方式: 1.利用有序索引获取有序数据 2.文件排序 在使用explain分析查询的时候,利用有序索引获取有序数据显示Using index.而文件排序显示 ...

  6. MySQL性能优化(七):其它优化

    原文:MySQL性能优化(七):其它优化 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/v ...

  7. mysql 序列与pg序列的比较

    mysql序列(这里只谈innodb引擎): 在使用mysql的AUTO_INCREMENT时,使用AUTO_INCREMENT的字段必须建有索引,也可以为索引的一部分.当没有索引时会报错:      ...

  8. mysql笔记03 查询性能优化

    查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...

  9. php面试专题---Mysql索引原理及SQL优化

    php面试专题---Mysql索引原理及SQL优化 一.总结 一句话总结: 注意:只写精品 1.为表设置索引要付出代价 是什么? 存储空间:一是增加了数据库的存储空间 修改插入变动索引时间:二是在插入 ...

随机推荐

  1. 前端vue项目js中怎么保证链式调用后台接口

    在一个for循环中对同一接口调用多次,如何保证逐步执行,同步执行. html部分 <DcFileUpload v-for="(item, index) of fileLengthLis ...

  2. wpf 代码设置图片路径(后台和xamll)

    项目中经常使用背景图片,当一个小组共通开发时,路径的选择应该是在项目运行的固定文件夹下 此时,可用代码实现:pack://SiteOfOrigin:,,,/Images/Icons/HomePageB ...

  3. Java基础之 集合体系结构(Collection、List、ArrayList、LinkedList、Vector)

    Java基础之 集合体系结构详细笔记(Collection.List.ArrayList.LinkedList.Vector) 集合是JavaSE的重要组成部分,其与数据结构的知识密切相联,集合体系就 ...

  4. 剑指offer 8:旋转数组的最小数字

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转 ...

  5. mysql dump备份 、 mysql还原操作练习

    1.备份mysql.dump 备份MySQL数据库的命令 mysqldump -h主机名 -u用户名 -p密码 数据库名字 > 备份的数据库名字.sql 例子: mysqldump -uroot ...

  6. XSS小游戏

    第一关 直接在URL输入 ?name=<script>alert('xss')</script> 第二关 找源码,输入test,value值变为test,我们可以在输入框尝试x ...

  7. Lodop打印表格带页头页尾 高度是否包含页头页尾 转载

    通过设置TableHeightScope,可以实现对ADD_PRINT_TABLE,表格带页头页尾,查看本博客另一篇博文:Lodop打印表格带页头页尾 自动分页每页显示头尾 超文本超过打印项高度,会自 ...

  8. python利用beautifulsoup多页面爬虫

    利用了beautifulsoup进行爬虫,解析网址分页面爬虫并存入文本文档: 结果: 源码: from bs4 import BeautifulSoup from urllib.request imp ...

  9. html表格及列表

    表格的属性: border:边框 cellpadding:内边距  单元格边框跟内容之间的间距 cellspacing:外边距  单元格跟单元格之间的距离 align:表格的对其样式 width:宽度 ...

  10. [C/C++]大小端字节序转换程序

    计算机数据存储有两种字节优先顺序:高位字节优先(称为大端模式)和低位字节优先(称为小端模式). 大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿 ...