MYSQL ORDER BY Optimization
ORDER BY Optimization
某些情况下,MYSQL可以使用index排序而避免额外的sorting.
即使order by语句列不能准确的匹配index,只要没有index中(不在order by的列)在where语句以常量形式出现。(最左前缀)
SELECT * FROM t1
ORDER BY key_part1,key_part2,... ; SELECT * FROM t1
WHERE key_part1 = constant
ORDER BY key_part2; SELECT * FROM t1
ORDER BY key_part1 DESC, key_part2 DESC; SELECT * FROM t1
WHERE key_part1 = 1
ORDER BY key_part1 DESC, key_part2 DESC; SELECT * FROM t1
WHERE key_part1 > constant
ORDER BY key_part1 ASC; SELECT * FROM t1
WHERE key_part1 < constant
ORDER BY key_part1 DESC; SELECT * FROM t1
WHERE key_part1 = constant1 AND key_part2 > constant2
ORDER BY key_part2;
某些情况下,依旧使用Index来查找匹配where子句的行,但MYSQL不用index来解决order by:
1:order by子句中使用不同indexes:
SELECT * FROM t1 ORDER BY key1, key2;
2:使用不连续的index部分(联合key的非最左前缀)
SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;
3:混合使用asc 和desc:
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
4:获得数据行的index(where子句中)和Order by 中使用的不一样:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
5:order by子句中使用index的表达式:
SELECT * FROM t1 ORDER BY ABS(key);
SELECT * FROM t1 ORDER BY -key;
6:join操作时,order by子句的列不全是第一个非 const表;
7: 不同的order by,group by表达式:
8:只对order by子句列的前缀加index,这种情况下index不能解决sort. e.g : order by列包含一个char(20)类型,但是只对前10bytes加index;
9:table index无序,the index of hash(memory表);
一个index是否排序可用可能受列的别名影响,表t1列 a 为索引:
可以利用index来排序:
SELECT a FROM t1 ORDER BY a;
不能:
SELECT ABS(a) AS a FROM t1 ORDER BY a;
该语句中,order by引用的是列a, select子句的列名也是a, 但是他是别名,引用的是abs(a);
下面的语句中,order by引用列名和select list中的列名不一样,但是select用到a,index sort可以使用(该语句的排序结果和以abs(a)排序的完全不一样)
SELECT ABS(a) AS b FROM t1 ORDER BY a;
默认的,mysql对所有的组col1,col2(group by col1,col2)排序,如果一个查询包含group by但是想避免sort的负载,可以压制排序通过order by null.
INSERT INTO foo
SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;
依赖隐式的group by 排序在mysql5.6中被舍弃。更可取的是使用准确的order by子句。
MYSQL有两种filesort算法来获得结果。原始的方法只使用order by中的列list. 改写过的方法不仅仅使用order by子句中的列,而是查询中所使用到的列。
优化器选择哪个filesort算法?正常情况下使用第二种(BLOB TEXT等大对象列外),两种算法,都使用到sort_buffer_size系统变量:
原始的filesort算法工作:
1:根据key值或者scan all the table(where条件)读取所有满足条件的行,跳过不满足where子句的行。
2:对于每一行,存储(key value, row id)对在sort buffer中。
3: 如果所有上述对能全部放在sort buffer中,临时文件不会被创建,否则,当sort buffer满时,内存中执行quicksort并且把结果写进临时文件中,保存一个指针执行这个 sorted block.
4:重复执行上述的过程,直到所有的行都被读取。
5:执行一个多路归并排序,把第一个文件的block转移到另外一个临时文件中。重复执行,直到第一个文件内容全部在第二个文件中。
6:一直merge buffer直到剩下2个block
7:最后一次merge,只写入rowid到结果表
8.根据排序结果中的rowid顺序读取数据。(手册中还提到了一个优化方案,但是我不认为能起到优化作用)。
该filesort中出现两次读取操作,第一次在where子句判断,另外一次是在拍完value pairs后。然而即使第一次访问是连续读取(e.g. scan all the table),但是第二次他们是随机访问(尽管key排过序了,但是行位置没有~!);
第二种filesort算法:(避开二次读,不是记录rowID,而是记录查询所使用的引用列)
1:读取满足where子句的所有行
2:对于每一行,元组记录key value和查询所引用到的列
3:当buffer满时,排序并写入临时文件
4:merge sort所有的临时文件,检索有序的行数据,直接从排过序的元组中读取需要的列而不是两次访问基表
修改后的方法,列长于原来的方法。很有可能会产生大量IO,让排序变得很慢。为了避免这个问题,优化器会所有读取列的长度小于max_length_for_sort_data系统变量,才会选择修改后的算法。
当filesort完成,explain输出中extra会有using filesort,优化器跟踪输出中filesort_summary块:
"filesort_summary": {
"rows": 100,
"examined_rows": 100,
"number_of_tmp_files": 0,
"sort_buffer_size": 25192,
"sort_mode": "<sort_key, additional_fields>"
}
其中sort mode就说了算法:
<sort_key,rowid>表示原始的算法
<sort_key,addtitional_filed>表示是修改后的算法
为了提高排序速度,可以检查是否可以使用索引,如果不能使用:
1.增加sort_buffer_size的大小
2.增加read_rnd_buffer_size的大小
3.通过表设计减少空间占用
4.修改tmpdir目录指向专用文件系统
如果order by没有使用索引,但是有limit子句,那么优化器可能可以避免合并临时文件,直接在内存中排序
MYSQL ORDER BY Optimization的更多相关文章
- 8.2.1.15 ORDER BY Optimization ORDER BY 优化
8.2.1.15 ORDER BY Optimization ORDER BY 优化 在一些情况下, MySQL 可以使用一个索引来满足一个ORDER BY 子句不需要做额外的排序 index 可以用 ...
- Mysql - ORDER BY详解
0 索引 1 概述 2 索引扫描排序和文件排序简介 3 索引扫描排序执行过程分析 4 文件排序 5 补充说明 6 参考资料 1 概述 MySQL有两种方式可以实现ORDER BY: 1.通过索引扫描生 ...
- MYSQL随机抽取查询 MySQL Order By Rand()效率问题
MYSQL随机抽取查询:MySQL Order By Rand()效率问题一直是开发人员的常见问题,俺们不是DBA,没有那么牛B,所只能慢慢研究咯,最近由于项目问题,需要大概研究了一下MYSQL的随机 ...
- MySQL Order By Rand()效率
最近由于需要大概研究了一下MYSQL的随机抽取实现方法.举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RA ...
- Mysql Order By 字符串排序,mysql 字符串order by
Mysql Order By 字符串排序,mysql 字符串order by ============================== ©Copyright 蕃薯耀 2017年9月30日 http ...
- mysql order by多个字段
Mysql order by 多字段排序 mysql单个字段降序排序: select * from table order by id desc; mysql单个字段升序排序: select * fr ...
- Mysql order by与limit混用陷阱
在Mysql中我们常常用order by来进行排序,使用limit来进行分页,当需要先排序后分页时我们往往使用类似的写法select * from 表名 order by 排序字段 limt M,N. ...
- MySQL ORDER BY主键id加LIMIT限制走错索引
背景及现象 report_product_sales_data表数据量2800万: 经测试,在当前数据量情况下,order by主键id,limit最大到49的时候可以用到索引report_produ ...
- mysql order by 排序的问题
参考博客http://blog.csdn.net/hollboy/article/details/13296601 mysql order by 的排序在今天时候遇到了问题 情景是:将排序的字段设置成 ...
随机推荐
- Jenkins 学习笔记(三):我们的JAVA 项目是这么发布的
发布拓扑 1. 拓扑图 2. 流程说明: Git 插件从 Git Server 上面拉取源代码. Maven 插件将源代码安装我们设定的指令进行编译打包,存放于项目的 WorkSpace. Publi ...
- 12.python进程\协程\异步IO
进程 创建进程 from multiprocessing import Process import time def func(name): time.sleep(2) print('hello', ...
- HTML、CSS、JS 复习——序
HTML在MVC中担任着M的角色.由HTML组成的节点称之为HTML DOM.要想成为一流的大神,就必须能分分钟建立起一个强大的HTML DOM.而要做到这点,就必须了解甚至精通HTML. CSS在M ...
- JS操作css样式用法
//html <div id="div1" style="background:red;"> 修改背景颜色 </div> <but ...
- [Spark SQL] SparkSession、DataFrame 和 DataSet 练习
本課主題 DataSet 实战 DataSet 实战 SparkSession 是 SparkSQL 的入口,然后可以基于 sparkSession 来获取或者是读取源数据来生存 DataFrameR ...
- java socket 和.net socket 通讯 demo
结束符协议"##" import java.io.BufferedReader; import java.io.IOException; import java.io.InputS ...
- Python爬虫下载美女图片(不同网站不同方法)
声明:以下代码,Python版本3.6完美运行 一.思路介绍 不同的图片网站设有不同的反爬虫机制,根据具体网站采取对应的方法 1. 浏览器浏览分析地址变化规律 2. Python测试类获取网页内容,从 ...
- linux搭建SS服务
基本准备: 购买主机:www.virmach.com LINUX系统操作经验:vim , apt-get 等命令的使用 putty.exe连接ssh工具的使用 开始 使用putty连接上去,并输入密码 ...
- Go 语言打包静态文件
对于 Go 语言开发者来说,在享受语言便利性的同时,最终编译的单一可执行文件也是我们所热衷的.但是,一旦遇到我们需要分发的东西不只有可执行文件的时候,事情就变得稍微有点复杂了,例如,需要分发个默认的配 ...
- CSS根据子元素个数不同定义样式
近日面试,遇见了一个这样的问题,不会,便记下来. 问题:如何根据子元素个数的不同定义不同的样式? 代码:HTML <ul> <li>1</li> <li> ...