Mysql序列(七)—— order by优化
前言
在mysql中满足order by的处理方式有两种:
- 让索引满足排序,即扫描有序索引然后再找到对应的行结果,这样结果即是有序;
- 使用索引查询出结果或者扫描表得到结果然后使用filesort排序;
filesort排序:是针结果在内存中进行排序,如果待排结果较大,mysql可能会产生临时文件输入输出到磁盘。
所以order by的优化思路
- 优先使用索引满足排序;
- 如果实在满足不了,再优化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是比表扫描更廉价。
从以上的几种情况中可以看出两种影响是否使用索引完成排序的因素:
使用扫描索引找出匹配的结果行是否比全表扫描找出结果带来更大的性能收益。如果用来全表扫描,那么肯定不会使用filesort;
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优化的步骤:
- 尽量让index方式完成order by:如何where和order by相同列则使用单索引列;如果不同使用联合索引;
- 无法使用时,对filesort方式进行调优;
参考
ORDER BY Optimization
Mysql order by与limit混用陷阱
mysql 大数据量分页优化
Mysql序列(七)—— order by优化的更多相关文章
- Mysql查询优化汇总 order by优化例子,group by优化例子,limit优化例子,优化建议
Mysql查询优化汇总 order by优化例子,group by优化例子,limit优化例子,优化建议 索引 索引是一种存储引擎快速查询记录的一种数据结构. 注意 MYSQL一次查询只能使用一个索引 ...
- MySql学习(七) —— 查询性能优化 深入理解MySql如何执行查询
本篇深入了解查询优化和服务器的内部机制,了解MySql如何执行特定查询,从中也可以知道如何更改查询执行计划,当我们深入理解MySql如何真正地执行查询,明白高效和低效的真正含义,在实际应用中就能扬长避 ...
- MySQL性能优化,MySQL索引优化,order by优化,explain优化
前言 今天我们来讲讲如何优化MySQL的性能,主要从索引方面优化.下期文章讲讲MySQL慢查询日志,我们是依据慢查询日志来判断哪条SQL语句有问题,然后在进行优化,敬请期待MySQL慢查询日志篇 建表 ...
- Mysql group by,order by,dinstict优化
1.order by优化 2.group by优化 3.Dinstinct 优化 1.order by优化 实现方式: 1. 根据索引字段排序,利用索引取出的数据已经是排好序的,直接返回给客户端: 2 ...
- mysql实战优化之六:Order by优化 sql优化、索引优化
在MySQL中的ORDER BY有两种排序实现方式: 1.利用有序索引获取有序数据 2.文件排序 在使用explain分析查询的时候,利用有序索引获取有序数据显示Using index.而文件排序显示 ...
- MySQL性能优化(七):其它优化
原文:MySQL性能优化(七):其它优化 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/v ...
- mysql 序列与pg序列的比较
mysql序列(这里只谈innodb引擎): 在使用mysql的AUTO_INCREMENT时,使用AUTO_INCREMENT的字段必须建有索引,也可以为索引的一部分.当没有索引时会报错: ...
- mysql笔记03 查询性能优化
查询性能优化 1. 为什么查询速度会慢? 1). 如果把查询看作是一个任务,那么它由一系列子任务组成,每个子任务都会消耗一定的时间.如果要优化查询,实际上要优化其子任务,要么消除其中一些子任务,要么减 ...
- php面试专题---Mysql索引原理及SQL优化
php面试专题---Mysql索引原理及SQL优化 一.总结 一句话总结: 注意:只写精品 1.为表设置索引要付出代价 是什么? 存储空间:一是增加了数据库的存储空间 修改插入变动索引时间:二是在插入 ...
随机推荐
- 微信小程序使用websocket通讯的demo,含前后端代码,亲测可用
目录 0.概述websocket 1.app.js写法 2.后台写法 0.概述websocket (1) 个人总结:后台设置了websocket地址,服务器开启后等待有人去连接它. 一个客户端一打开就 ...
- mysql Waiting for table flush
应用突然被hang住了,tomcat日志报错,所有涉及到数据库的操作都报错,卡死. show processlist 查看到大量的:Waiting for table flush 应该是 进行了 dd ...
- Windows下面startup.bat启动Tomcat偶发死锁问题
Windows下面startup.bat启动Tomcat时,因为日志都打印到了cmd里面,存在偶发卡死Tomcat的问题,该问题确认是Windows系统的问题,而且一直没有解决.解决的办法是把日志重定 ...
- flask uwsgi和nginx配置信息
1. 安装 pip3 install uwsgi 2. uwsgi配置信息 创建一个uwsgi.ini文件 [uwsgi] socket=/opt/script/uwsgi.sock #启动程序时所使 ...
- 其他综合-CentOS7 安装 Jumpserver 跳板机
CentOS7 安装 Jumpserver 跳板机 1.实验描述 搭建 jumpserver 平台,实现有效的运维安全审计.完美做到事先防范,事中控制和事后溯源 2.实验环境 物理机系统:Window ...
- 其他综合-CentOS 7 使用yum 安装 PHP 5.6
其他综合-CentOS 7 使用yum 安装 PHP 5.6 1.删除旧php包 yum remove php.x86_64 php-cli.x86_64 php-common.x86_64 php- ...
- HttpWatch功能详细介绍
来源:https://www.cnblogs.com/Chilam007/p/6947235.html HttpWatch是功能强大的网页数据分析工具,集成在IE工具栏,主要功能有网页摘要.cooki ...
- XSS-DOM
DOM型XSS是基于DOM文档对象模型的一种漏洞 通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问.所有 HTML 元素(节点)均可被修改,也可以创建或删除节点.(引用W ...
- UiPath:取系统时间/分取各个时间/修改时间显示格式
取系统时间/分取各个时间/修改时间显示格式解决方法: system_time.Year.ToString+"年"+system_time.Month.ToString+" ...
- day6_面向对象的概念
#!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2019/7/11 16:20 # @Author : 大坏男孩 # @File : d ...