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的更多相关文章

  1. 8.2.1.15 ORDER BY Optimization ORDER BY 优化

    8.2.1.15 ORDER BY Optimization ORDER BY 优化 在一些情况下, MySQL 可以使用一个索引来满足一个ORDER BY 子句不需要做额外的排序 index 可以用 ...

  2. Mysql - ORDER BY详解

    0 索引 1 概述 2 索引扫描排序和文件排序简介 3 索引扫描排序执行过程分析 4 文件排序 5 补充说明 6 参考资料 1 概述 MySQL有两种方式可以实现ORDER BY: 1.通过索引扫描生 ...

  3. MYSQL随机抽取查询 MySQL Order By Rand()效率问题

    MYSQL随机抽取查询:MySQL Order By Rand()效率问题一直是开发人员的常见问题,俺们不是DBA,没有那么牛B,所只能慢慢研究咯,最近由于项目问题,需要大概研究了一下MYSQL的随机 ...

  4. MySQL Order By Rand()效率

    最近由于需要大概研究了一下MYSQL的随机抽取实现方法.举个例子,要从tablename表中随机提取一条记录,大家一般的写法就是:SELECT * FROM tablename ORDER BY RA ...

  5. Mysql Order By 字符串排序,mysql 字符串order by

    Mysql Order By 字符串排序,mysql 字符串order by ============================== ©Copyright 蕃薯耀 2017年9月30日 http ...

  6. mysql order by多个字段

    Mysql order by 多字段排序 mysql单个字段降序排序: select * from table order by id desc; mysql单个字段升序排序: select * fr ...

  7. Mysql order by与limit混用陷阱

    在Mysql中我们常常用order by来进行排序,使用limit来进行分页,当需要先排序后分页时我们往往使用类似的写法select * from 表名 order by 排序字段 limt M,N. ...

  8. MySQL ORDER BY主键id加LIMIT限制走错索引

    背景及现象 report_product_sales_data表数据量2800万: 经测试,在当前数据量情况下,order by主键id,limit最大到49的时候可以用到索引report_produ ...

  9. mysql order by 排序的问题

    参考博客http://blog.csdn.net/hollboy/article/details/13296601 mysql order by 的排序在今天时候遇到了问题 情景是:将排序的字段设置成 ...

随机推荐

  1. 页面刷新vuex数据消失问题解决方案 之 vuex中间件

    之前我写了一篇用ES6 Proxy方案解决数据同步的文章 页面刷新vuex数据消失问题解决方案. 今天和同事沟通这个vuex数据还原问题,我说我的方法很奇异.聊着聊着,同事咋不用  store.sub ...

  2. Python爬虫知识点二

    一.request库 import json import requests from io import BytesIO #显示各种函数相当于api # print(dir(requests)) u ...

  3. vscode 开发工具

    做开发两年了,而我记忆力不太好,所以写代码得靠强大的编辑器提示. 陆陆续续使用了如 notepad++.dreamweaver.sublime text.webstorm.phpstorm.Atom等 ...

  4. python并开发编程之协程

    一 引出协成 并发的本质是:切换+保存状态 CPU在运行行一个任务时,会在两种情况下切走去执行其他任务,一是该任务发生了阻塞,二是运行该任务的时间过长 yeild可以保存状态,yeild状态保存与操作 ...

  5. python之 正则表达式

    简介 Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式.Python 1.5之前版本则是通过 regex 模块提供 Emacs 风格的模式.Emacs 风格模式可读 ...

  6. 冒泡算法给0~9随机n位数字排序

    <?php //产生5位0~9的随机数      function getRand($begin=0,$end=9,$limit=5){                $rand_array=r ...

  7. 通过Chocolatey软件包管理器安装.NET Core

    在Linux的世界里,有了yum/apt-get百分之九十的软件都可以通过它来安装管理.但是在Windows系统上,装个软件还是挺折腾的.比如我要装个Chrome浏览器,我先得打开IE浏览器吧,我还打 ...

  8. 解决api 跨域 webconfig添加节点

    <system.webServer><httpProtocol><customHeaders><add name="Access-Control-A ...

  9. tornado SSL 证书获取与服务器配置

    转载注明出处: http://www.cnblogs.com/ityoung/p/8296088.html 自动化测试/持续集成/测试开发 QQ交流群: 70160503 服务端生成证书 进入 ope ...

  10. 如何获取离线安装Chrome扩展程序的包

    最近工作环境限制,有些机器文件只能拿进去,不能拿出来.网络也是内部网络,没法下载东西.工作中常用的一些Chrome扩展应用也没法使用,对于我这类工具爱好者,打击够大.后来想想,既然扩展应用能开发打包上 ...