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. Jenkins 学习笔记(三):我们的JAVA 项目是这么发布的

    发布拓扑 1. 拓扑图 2. 流程说明: Git 插件从 Git Server 上面拉取源代码. Maven 插件将源代码安装我们设定的指令进行编译打包,存放于项目的 WorkSpace. Publi ...

  2. 12.python进程\协程\异步IO

    进程 创建进程 from multiprocessing import Process import time def func(name): time.sleep(2) print('hello', ...

  3. HTML、CSS、JS 复习——序

    HTML在MVC中担任着M的角色.由HTML组成的节点称之为HTML DOM.要想成为一流的大神,就必须能分分钟建立起一个强大的HTML DOM.而要做到这点,就必须了解甚至精通HTML. CSS在M ...

  4. JS操作css样式用法

    //html <div id="div1" style="background:red;"> 修改背景颜色 </div> <but ...

  5. [Spark SQL] SparkSession、DataFrame 和 DataSet 练习

    本課主題 DataSet 实战 DataSet 实战 SparkSession 是 SparkSQL 的入口,然后可以基于 sparkSession 来获取或者是读取源数据来生存 DataFrameR ...

  6. java socket 和.net socket 通讯 demo

    结束符协议"##" import java.io.BufferedReader; import java.io.IOException; import java.io.InputS ...

  7. Python爬虫下载美女图片(不同网站不同方法)

    声明:以下代码,Python版本3.6完美运行 一.思路介绍 不同的图片网站设有不同的反爬虫机制,根据具体网站采取对应的方法 1. 浏览器浏览分析地址变化规律 2. Python测试类获取网页内容,从 ...

  8. linux搭建SS服务

    基本准备: 购买主机:www.virmach.com LINUX系统操作经验:vim , apt-get 等命令的使用 putty.exe连接ssh工具的使用 开始 使用putty连接上去,并输入密码 ...

  9. Go 语言打包静态文件

    对于 Go 语言开发者来说,在享受语言便利性的同时,最终编译的单一可执行文件也是我们所热衷的.但是,一旦遇到我们需要分发的东西不只有可执行文件的时候,事情就变得稍微有点复杂了,例如,需要分发个默认的配 ...

  10. CSS根据子元素个数不同定义样式

    近日面试,遇见了一个这样的问题,不会,便记下来. 问题:如何根据子元素个数的不同定义不同的样式? 代码:HTML <ul> <li>1</li> <li> ...