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 的排序在今天时候遇到了问题 情景是:将排序的字段设置成 ...
随机推荐
- Android Studio移动鼠标显示悬浮提示的设置方法
欢迎和大家交流技术相关问题: 邮箱: jiangxinnju@163.com 博客园地址: http://www.cnblogs.com/jiangxinnju GitHub地址: https://g ...
- SqlServer Lock_Escalation
在今天的文章里,我想谈下SQL Server里锁升级(Lock Escalations).锁升级是SQL Server使用的优化技术,用来控制在SQL Server锁管理里把持锁的数量.我们首先用SQ ...
- celery出现警告或异常的解决方式
做个笔记,记录下使用celery踩过的坑,不定期更新. warnings.warn(CDeprecationWarning(W_PICKLE_DEPRECATED)) 我用的是Flask,所以在Fl ...
- Python的__getattr__和__getattribute__
__getattr____getattr__在当前主流的Python版本中都可用,重载__getattr__方法对类及其实例未定义的属性有效.也就属性是说,如果访问的属性存在,就不会调用__getat ...
- 如何用Fritzing实现元器件自定义接线图
在用Micropython开发板完成小实验时,很多朋友反应对照接线图实际接线有时会有一些困扰.今天给大家介绍一款画图软件Fritzing 看看是怎么自定义制作接线图的. 前提条件 1.准备好元器件 ...
- Winform跨窗体操作控件(使用委托)
Winform跨窗体操作控件是winform开发中很常见的形式,最常见且简单有效的方式便是使用委托的方式来进行操作,下面我将通过一个小实例来说明如何使用委托跨窗体实现控件操作. 实例介绍:两个窗体,F ...
- entity framework学习
资源 Entity Framework技术导游系列开篇与热身
- DeepLearning.ai学习笔记(四)卷积神经网络 -- week2深度卷积神经网络 实例探究
一.为什么要进行实例探究? 通过他人的实例可以更好的理解如何构建卷积神经网络,本周课程主要会介绍如下网络 LeNet-5 AlexNet VGG ResNet (有152层) Inception 二. ...
- [转载]mysql中实现行号,oracle中的rowid
mysql中实现行号需要用到MYSQL的变量,因为MySql木有rownumber. MYSQL中变量定义可以用 set @var=0 或 set @var:=0 可以用=或:=都可以,但是如果变量用 ...
- MYSQL:python 3.x连接数据库的方式
我们想要在我们的mython程序中使用mysql,首先需要安装pymysql模块,安装方式可以使用cmd命令安装, pip3.x install pymysql 首先在我们连接数据库之前先创建一个us ...