ORDER BY Optimization

某些情况下,MYSQL可以使用index排序而避免额外的sorting.

即使order by语句列不能准确的匹配index,只要没有index中(不在order by的列)在where语句以常量形式出现。(最左前缀)

  1. SELECT * FROM t1
  2. ORDER BY key_part1,key_part2,... ;
  3.  
  4. SELECT * FROM t1
  5. WHERE key_part1 = constant
  6. ORDER BY key_part2;
  7.  
  8. SELECT * FROM t1
  9. ORDER BY key_part1 DESC, key_part2 DESC;
  10.  
  11. SELECT * FROM t1
  12. WHERE key_part1 = 1
  13. ORDER BY key_part1 DESC, key_part2 DESC;
  14.  
  15. SELECT * FROM t1
  16. WHERE key_part1 > constant
  17. ORDER BY key_part1 ASC;
  18.  
  19. SELECT * FROM t1
  20. WHERE key_part1 < constant
  21. ORDER BY key_part1 DESC;
  22.  
  23. SELECT * FROM t1
  24. WHERE key_part1 = constant1 AND key_part2 > constant2
  25. ORDER BY key_part2;

某些情况下,依旧使用Index来查找匹配where子句的行,但MYSQL不用index来解决order by:

1:order by子句中使用不同indexes:

  1. SELECT * FROM t1 ORDER BY key1, key2;

2:使用不连续的index部分(联合key的非最左前缀)

  1. SELECT * FROM t1 WHERE key2=constant ORDER BY key_part2;

3:混合使用asc 和desc:

  1. SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;

4:获得数据行的index(where子句中)和Order by 中使用的不一样:

  1. SELECT * FROM t1 WHERE key2=constant ORDER BY key1;

5:order by子句中使用index的表达式:

  1. SELECT * FROM t1 ORDER BY ABS(key);
  2. 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来排序:

  1. SELECT a FROM t1 ORDER BY a;

不能:

  1. 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)排序的完全不一样)

  1. SELECT ABS(a) AS b FROM t1 ORDER BY a;

默认的,mysql对所有的组col1,col2(group by col1,col2)排序,如果一个查询包含group by但是想避免sort的负载,可以压制排序通过order by null.

  1. INSERT INTO foo
  2. 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块:

  1. "filesort_summary": {
  2. "rows": 100,
  3. "examined_rows": 100,
  4. "number_of_tmp_files": 0,
  5. "sort_buffer_size": 25192,
  6. "sort_mode": "<sort_key, additional_fields>"
  7. }

其中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. Java求循环节长度

    两个整数做除法,有时会产生循环小数,其循环部分称为:循环节.比如,11/13=6=>0.846153846153.....  其循环节为[846153] 共有6位.下面的方法,可以求出循环节的长 ...

  2. 02-01官网静默模式安装WebLogic

    参考连接:https://docs.oracle.com/middleware/11119/wls/WLSIG/silent.htm#CIHCAHGC 以静默模式运行安装程序 本章介绍如何以静默方式运 ...

  3. Nginx集群之WCF分布式局域网应用

    目录 1       大概思路... 1 2       Nginx集群WCF分布式局域网结构图... 1 3       关于WCF的BasicHttpBinding. 1 4       编写WC ...

  4. Upgrade with the Gradle Wrapper, gradlew升级

    springboot 2.0需要gradle 1+, 而自动构建的都是3.+,手动升级如下 Upgrade with the Gradle Wrapper If your existing Gradl ...

  5. NUnit实战,第一个测试类,测试事件触发是否是并行的

    以前测试都是新建一个控制台测试的方式来进行,感觉版本管理啥的非常麻烦.也是非常原始的办法.后来想以前有写过测试单元,不过好久没弄了.Nuget了NUnit后写了正式的第一个测试类. 测试用例: 测试事 ...

  6. android官网文档学习笔记

    1.android的四大组件的了大概功能 activity:负责显示界面,和用户交互. service:运行在后台. content provider:为程序app之间的数据访问提供接口. broad ...

  7. 强化学习之Sarsa (时间差分学习)

    上篇文章讲到Q-learning, Sarsa与Q-learning的在决策上是完全相同的,不同之处在于学习的方式上 这次我们用openai gym的Taxi来做演示 Taxi是一个出租车的游戏,把顾 ...

  8. 优雅的处理Redis访问超时

    很长一段时间以来,一直在项目中使用Redis作为辅助存储,确切来说是利用Redis的内存存储,而不是将其作为缓存.比如常见的利用Set集合来判断某个数值是否存在,或者将来自不同请求的数据放在Redis ...

  9. Sampling

    本文主要涉及接受拒绝采样,重要性采样,蒙特卡洛方法,吉布斯采样等内容.部分内容整理与互联网.仅供交流学习使用!

  10. 利用cmd制作一句话图片马

    先cd进在图片和一句话木马里面的文件夹 假设选择我的图片是:1.jpg 一句话是:2.php 命令:copy 1.jpg/a+2.php/b 生成的图片马