MySQL提供了两种排序算法操作(即ORDERBY操作,所以理解排序算法有助于理解ORDERBY优化),在查询执行计划中用“filesort”表示使用了外部文件进行排序。第一种算法是双路排序算法,只利用ORDERBY子句中包括的列对象进行排序(适用于有BLOB、TEXT类型的列对象参与的排序);第二种算法是单路排序算法,除利用ORDERBY子句中包括的列对象外,还利用查询目标列中的所有列对象进行排序(适用于除BLOB、TEXT类型外的所有的其他类型的排序)。

算法一:双路排序算法的完整实现过程如下:

1)        按索引键或全表扫描的方式,读取所有的元组,不匹配WHERE子句的元组被跳过;第一步需要从存储读入数据,引发I/O操作。

2)        对于每一行,在缓冲区中存储一对值(对值,包括排序关键字和元组指针)。缓冲区的大小是系统变量的sort_buffer_size设定的值。

3)        当缓冲区已满,运行快排算法(快速排序,qsort)对一个块中的数据进行排序,将结果存储在一个临时文件。保存一个指向排序后的块的指针(如果第二步所说的对值都能被缓冲区容纳,则不会创建临时文件)。

4)        重复上述步骤,直到所有的行已经被读取。

5)        执行一个多路归并操作(操作对象是第三步生成的每一个有序的块)汇集到“MERGEBUFF域”,然后存放到在第二个临时文件中。重复操作,直到第一个文件的所有块归并后存入到第二个文件;“MERGEBUFF域”是代码sql_sort.h中定义的宏,值为7。

6)        重复以下操作(第7步和第8步),直到留下少于“MERGEBUFF2域”标明的块数为止;“MERGEBUFF2域”是代码sql_sort.h中定义的宏,值为15。

7)        在最后一次多路归并操作中,把元组的指针(排序关键字的最后部分)写入到一个结果文件。

8)        在结果文件中,按照排列的顺序使用元组指针读取元组(为了优化这项操作,MySQL读入元组指针进入一个大的块,对块中元组指针进行排序而不是直接对数据排序,然后再用有序的元组指针获取元组到元组缓存,元组缓冲区的大小由read_rnd_buffer_size参数控制)。第8步需要从存储读入数据,引发I/O操作。

算法二:单路排序算法,改进算法一,减少一次I/O,需要增加缓冲区大小容纳更多信息。其具体实现过程如下:

1)        获取与WHERE子句匹配的元组。这一步需要从存储读入数据,引发I/O操作。

2)        对于每一个元组,记录排序键值、行的位置值、查询所需的列。这一步记录更多内容,需要更大缓存,内存存储一条元组的信息的长度比算法一的“对值”大许多,这可能引发排序速度问题(排序对象的长度变长,但是内存有限,所以就需把一次内存排序变为多次,进而影响排序的速度),为了控制这个问题,MySQL引入一个参数“max_length_for_sort_data”,如果这一步得到的元组长度大于这个值,则不使用算法二。需要MySQL的使用者特别注意的是,在排序中,如果存在“很高磁盘I/O和很低的CPU利用率”的现象,则需要考虑调整“max_length_for_sort_data”的大小以变更换排序算法。

3)        按照排序的键值,对元组(元组是第二步的结果)进行排序。

算法二直接从缓冲区中的排序的元组中获取有序的列信息等(查询的目的对象),而不是第二次访问该表读取所需的列。相比算法一减少一次I/O。

MySQL支持对于ORDERBY的优化,,下面我们通过具体示例说明。

首先让我们做一些准备工作。创建表,命令如下:

CREATE TABLE t_o1 (a1 INT UNIQUE, b1 INT);

CREATE TABLE t_o2 (a2 INT UNIQUE, b2 INT);

示例1在索引列上进行排序操作,MySQL支持利用索引进行排序优化。

在一个表的索引列上执行排序操作,查询执行计划如下:

mysql> EXPLAIN SELECT * FROM t_o1 ORDER BY a1;

+----+-------------+-------+------+------+----------------+

| id | select_type | table | type | key  | Extra          |

+----+-------------+-------+------+------+----------------+

|  1 | SIMPLE      | t_o1  | ALL  | NULL |Using filesort|

+----+-------------+-------+------+------+----------------+

1 row in set (0.00 sec)

从查询执行计划看,对表进行了全表扫描,并进行了排序操作(Using filesort)。没有利用索引对排序进行优化。

对索引列进行查询,查询执行计划如下:

mysql> EXPLAIN SELECT a1 FROM t_o1 ORDER BY a1;

+----+-------------+-------+-------+------+-------------+

| id | select_type | table | type  | key  | Extra       |

+----+-------------+-------+-------+------+-------------+

|  1 | SIMPLE      | t_o1  | index | a1   | Using index |

+----+-------------+-------+-------+------+-------------+

1 row in set (0.00 sec)

从查询执行计划看,对表进行了索引扫描,利用索引对排序进行优化。对比上一条SQL语句,不同之处在于目标列不同,本条SQL语句的目标列是索引列,不是表的全部字段。这说明MySQL支持利用索引消除排序的技术,但只限于目标列也是索引列。

示例2排序下推,MySQL不支持。在非索引列上执行连接,然后排序,查询执行计划如下:

mysql> EXPLAIN EXTENDED SELECT * FROM t_o1, t_o2 WHERE b1=b2  ORDER BY b1;

+----+-------------+-------+------+-------+----------------------------------------------------+

| id | select_type | table | type |  key  | Extra                                              |

+----+-------------+-------+------+-------+----------------------------------------------------+

|  1 | SIMPLE      | t_o1  | ALL  |  NULL | Using temporary; Using filesort                    |

|  1 | SIMPLE      | t_o2  | ALL  |  NULL | Using where; Using join buffer (Block Nested Loop) |

+----+-------------+-------+------+-------+----------------------------------------------------+

2 rows in set (0.00 sec)

从查询执行计划看,在表t_o1上分别进行了全表扫描后与t_o2表进行了连接,然后用临时文件完成排序。这表明MySQL不可以把排序下推到基表单执行,然后再连接,不支持排序下推优化技术。

mysql spj_MySQL查询优化器--非SPJ优化--ORDERBY优化相关推荐

  1. mysql spj_MySQL查询优化器--非SPJ优化--LIMIT优化

    MySQL支持对不带HAVING子句的LIMIT进行优化,主要的优化点包括: LIMIT对单表扫描的影响:如果索引扫描可用且花费低于全表扫描,则用索引扫描实现LIMIT(LIMIT取很少量的行,否则优 ...

  2. Mysql之查询优化器 EXPLAIN 详解

    了解查询优化器 查询瓶颈 CPU饱和(读取数据至内存 or 将数据持久化至硬盘) IO饱和(读取数据远大于内存容量) 硬件制约(top,free,iostat,vmstat等系统性能状态) 执行计划( ...

  3. 如何阅读《数据库查询优化器的艺术:原理解析与SQL性能优化》

    附录B 如何阅读本书 本书是一本数据库内核相关书籍,从数据库的查询优化器入手,对数据库的查询优化引擎进行了分析和对比,对查询优化的技术做了全面的总结和剖析.从不同角度看,可能有着不同的感受:不同角色的 ...

  4. MySQL优化器_MySQL查询优化器

    MySQL优化器 MySQL架构图 讲到MySQL,就绕不开他的架构图.MySQL是一个经典的C/S架构.服务器这边分两层:第一层是Server层,第二层是存储引擎.Server层处理主要的业务操作流 ...

  5. mysql 优化器代码_Mysql查询优化器

    Mysql查询优化器 本文的目的主要是通过告诉大家,查询优化器为我们做了那些工作,我们怎么做,才能使查询优化器对我们的sql进行优化,以及启示我们sql语句怎么写,才能更有效率.那么到底mysql到底 ...

  6. mysql 优化器提示_Mysql查询优化器

    Mysql查询优化器 本文的目的主要是通过告诉大家,查询优化器为我们做了那些工作,我们怎么做,才能使查询优化器对我们的sql进行优化,以及启示我们sql语句怎么写,才能更有效率.那么到底mysql到底 ...

  7. mysql 关联查询_Mysql查询优化器,再也不会因为该什么时候建立索引发愁了

    优化器的作用: 我们知道,一条SQL语句,可以有很多执行方式,最后都返回相同的结果,而优化器的作用就是找到最好的执行计划. 一.RBO-基于规则的优化器(rule) 系统内置的一套硬编码规则,根据规则 ...

  8. MySQL查询优化器工作原理解析

    手册上查询优化器概述 查询优化器的任务是发现执行SQL查询的最佳方案.大多数查询优化器,包括MySQL的查询优化器,总或多或少地在所有可能的查询评估方案中搜索最佳方案.对于联接查询,MySQL优化器所 ...

  9. mysql查询比对提速_MySQL查询性能优化

    关注我,更多精彩文章第一时间推送给你 1.为什么查询速度会慢? ​首先对一个查询的生命周期简化分析,大致可以按照顺序分为:从客户端.到服务器.然后在服务器进行解析.生成执行计划.执行.并返回结果给客户 ...

  10. MySQL教程——3 中级篇(存储引擎、优化SQL步骤、索引的使用)

    Mysql高级-day02 1. Mysql的体系结构概览 整个MySQL Server由以下组成 Connection Pool : 连接池组件 Management Services & ...

最新文章

  1. 上市公司财务报表分析——以中国联通为例
  2. UIVisualEffectView实现毛玻璃效果
  3. 皮一皮:是亲爹的操作 ,没错...
  4. 【EventBus】EventBus 使用示例 ( 最简单的 EventBus 示例 )
  5. 【译】在Android中保护数据-加密大数据
  6. 线程wait()和sleep()的区别
  7. 使用vi/vim编辑时按ctrl-s后客户端假死解决方法
  8. Android-用ListView显示SDCard文件列表
  9. PHP_TP5框架开发后端接口(代码编写思路)
  10. 听说社保不能补缴了,像我们这种没缴社保的打工者,该怎么办?
  11. Home_W的位运算(位运算+预处理)
  12. 【医疗影像处理】去除医疗影像中背景的影响2D/3D【numpy-code】
  13. Leetcode 刷题笔记(二) —— 数组类型解题方法二:双指针法
  14. 静态初始化中不能放入繁重计算,否则会变慢!
  15. ecshop 影响全局的标量lib_main.php
  16. SVM支撑向量机原理
  17. 取消锚(a/)点击后页面跳转的几种方法
  18. 基于bim二次开发的智能楼宇管理系统
  19. 【NLP】第 6 章:XGBoost 超参数
  20. 别以为太简单!创建最好邮件营销内容的13个技巧

热门文章

  1. [微信]微信小程序开发--用户昵称中带有emoji表情的处理方法
  2. 开灯问题 算法竞赛 (注释详细)
  3. Lua 源码学习笔记(2)字符串
  4. win ollvm环境_打造舒适搬砖环境,这些是我最想推介的桌面好物
  5. 修改用友服务器ip地址,修改用友服务器ip地址
  6. linux添加mx记录,在C linux中查询MX记录
  7. 不看后悔!圈内老手总结的18条嵌入式 C 实战经验
  8. Macbook安装双系统的方法
  9. Mac OSX配置XAMP虚拟主机
  10. jmeter监控服务器插件jp@gc - PerfMon Metrics Collector报错 Operation timed out