针对排序来讲,order by 是咱们使用很是频繁的关键字。结合以前咱们对索引的了解再来看这篇文章会让咱们深入理解在排序的时候,是如何利用索引来达到少扫描表或者使用外部排序的。优化
先定义一个表辅助咱们后面理解spa
CREATE TABLE `t` ( `id` int(11) NOT NULL, `city` varchar(16) NOT NULL, `name` varchar(16) NOT NULL, `age` int(11) NOT NULL, `addr` varchar(128) DEFAULT NULL, PRIMARY KEY (`id`), KEY `city` (`city`) ) ENGINE=InnoDB;
这时咱们写一条查询语句线程
select city,name,age from t where city='杭州' order by name limit 1000 ;
根据上面的表定义来看,city=xxx 可使用到咱们定义的一个索引。可是 order by name 明显咱们没有索引,因此确定须要先用索引查询到 city=xxx 而后再进行回表查询,最后再排序。code
全字段排序blog
在 city 字段上面建立索引以后,咱们使用执行计划来查看这个语句 排序
能够看到有索引的状况下 咱们这里仍是使用了 "Using filesort" 表示须要排序,MySQL 会给每一个线程分配一块内存用于排序 称为 sort_buffer。索引
咱们在执行上面 select 语句的时候一般经历了这样一个过程内存
1. 初始化 sort_buffer, 确认放入 name, city, age 这三个字段。ci
2. 从索引 city 找到第一个知足 city='杭州'条件的主键 id。it
3. 回表取到 name, city, age 三个字段值,存入 sort_buffer 中。
4. 从索引 city 取下一个主键 id 记录。
5. 重复 3-4 步骤,直到 city 不知足条件。
6. 对 sort_buffer 中的数据按照字段 name 作快速排序。
7. 排序结果取前 1000 行返回给客户端。
这被咱们称为全字段排序。
按照 name 排序这个动做便可能在内存中完成,也能够能使用外部文件排序。这取决于 sort_buffer_size 。sort_buffer_size 的默认值是 1048576 byte 也就是 1M,若是要排序的数据量小于 1m 排序就在内存中完成,若是排序数据量大,内存放不下,则使用磁盘临时文件辅助排序。
Rowid 排序
若是单行很大,须要的字段所有放进 sort_buffer 效果就不会很好。
MySQL 中专门用于控制排序的行数据长度有个参数 max_length_for_sort_data 默认是1024,若是超过了这个值就会使用 rowid 排序。那么执行上面语句的流程就变成了
1. 初始化 sort_buffe 肯定放入两个字段即 name 和 id 。
2. 从索引 city 找到第一个知足 city = '杭州'条件的主键 id。
3. 回表取 name 和 id 两个字段 存入 sort_buffer 中。
4. 取下个知足条件的记录 重复 2 3 步骤。
5. 对 sort_buffer 中的 name 进行排序。
6.遍历结果取前 1000 行。而后按照 id 再回一次表取的结果字段返回给客户端。
其实并非全部 oder by 语句都须要进行上面的二次排序操做。从上面分析的执行过程,咱们能够注意到。MySQL 之因此须要生成临时表,是由于要在临时表上作排序,是由于以前咱们取得的是数据是无序的。
若是咱们对刚才的索引修改一下,使得他是一个联合索引,那么第二个字段咱们拿到的值其实就是有序的了。
联合索引知足这么一个条件,当咱们的第一个索引字段是相等的状况下,第二个字段是有序的。
这能保证若是咱们创建 (city,name) 索引的话,当咱们在搜索 city='杭州'的状况的是时候找到的目标第二个字段 name 实际上是有序的。因此查询过程能够简化成。
1. 从索引 (city, name) 找到第一个知足 city = '杭州'条件的主键 id 。
2. 回表取到 name city age 三个值返回。
3. 取下一个 id 。
4. 重复2 3 两个步骤直到 1000 条记录,或者是不知足 city = '杭州'条件结束。
也由于查询过程均可以使用到索引的有序性,因此再也不须要排序也不须要时使用 sort buffer 了。
更近一步的优化就是以前说过的索引覆盖,将须要查询的字段也覆盖进索引中,再省掉回表的步骤,可让整个查询的速度更快。
Reference:
本读书笔记皆来自发布在极客时间的 林晓斌(丁奇)的 MySQL 实战45讲:
极客时间版权全部: https://time.geekbang.org/ 版权全部:
https://time.geekbang.org/column/article/73479