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. Head First设计模式之单例模式

    一.定义 保证一个类仅有一个实例,并提供一个访问它的全局访问点.通过单例模式可以保证系统中一个类只有一个实例.即一个类只有一个对象实例. Singleton模式中的实例构造器可以设置为protecte ...

  2. [Micropython]发光二极管制作炫彩跑马灯

       先甩锅 做完后才发现最后一个灯坏了,就坏了一个灯也不好意思去找淘宝店家,大家视频凑合着看把.不过并不影响实验效果.因为这个发光二极管白天不是很明显 晚上炫彩效果就能出来了.本次实验用的是8个灯珠 ...

  3. Oracle COMMIT语句的处理顺序

    Oracle COMMIT语句相信大家都有一定的了解,下面就为您介绍Oracle COMMIT语句的处理步骤,希望对您能有所帮助. Oracle COMMIT语句处理顺序 当事务提交时,Oracle分 ...

  4. 关于 for 循环与 循环嵌套

    FOR循环精讲 > 1.初步结识 for是写出题的重要组成部分之一,每个题如果没有for循环根本是无法做出来的,可见for循环在c++语言中是有多么重要,那么for的格式是怎样的呢?? for( ...

  5. navicat for sqlite 11.1.12 patch 永久试用 不报毒

    因为最近需要用这个但是网上都是注册机没有成功注册,所以就自己动手使用ollydbg开刀,    修改成了永久试用版本. 着急用所以没仔细分析,暂时先这样吧. 这个下载版本 http://dlsw.ba ...

  6. COM学习(三)——COM的跨语言

    COM是基于二进制的组件模块,从设计之初就以支持所有语言作为它的一个目标,这篇文章主要探讨COM的跨语言部分. idl文件 一般COM接口的实现肯定是以某一具体语言来实现的,比如说使用VC++语言,这 ...

  7. ssm工程集成mybatis分页插件pagehelper

    1    首先需要在mybatis的配置文件SqlMapConfig.xml文件中配置pagehelper插件 <plugins> <plugin interceptor=" ...

  8. 使用jemeter手工编写注册、登陆脚本 运用 fiddler (一)

    我们要使用jemeter来手工写一个脚本 我们要使用到两个工具 一个 就是  jmeter  一个就是 fiddler 为什么要使用fiddler   ? 因为能够帮我们正确精准的找到我们需要的数据 ...

  9. Zabbix实战-简易教程--动作(Actions)--自动发现

    一.概述 Zabbix提供了有效和非常灵活的网络自动发现功能. 设置网络发现后你可以: 加快Zabbix部署(自动添加主机.添加模板) 简化管理(自动删除主机.删除模板.禁用主机) 无需过多管理就能在 ...

  10. 谈谈关键字new

    1.在情人节那天,无意间看到空间有人说,没有对象就new一个,然后就可以........ 程序中我们常用到X a=new X(), new在这里是创建一个对象,也可以叫做创建一个实例,我们先谈谈后半部 ...