03.18 Day 59 - order by 的算法流程

大家好,我是 Snow Hide,作为《MySQL 实战》这个专栏的学员之一,这是我打卡的第 59 天,也是我第 121 次进行这种操作。

今天我温习了该专栏里一篇叫《“order by”是怎么工作的?》的文章。

关键词总结:全字段排序(语句的执行流程、MySQL 需要 12 个临时文件来做排序的原因)、row_id(指定排序的行数据长度后所采用的另一种算法、由于行数据长度过短导致排序结果少了 city 和 age 后整个执行的流程)、全字段排序 VS rowid 排序(创建 city 和 name 联合索引、city 满足一个值之后name 的值就一定是有序的、创建 city、name 和 age 联合索引、对于 city 字段值相同的行来说 name 字段的值递增也是递增排序)。

所学总结:

全字段排序

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  ;

语句的执行流程

  1. 初始化 sort_number,确定放入 name、city、age 这三个字段;
  2. 从索引 city 找到第一个满足 city=‘杭州’ 条件的主键 id;
  3. 到主键 id 索引取出整行,取 name、city、age 三个字段的值,存入 sort_buffer 中;
  4. 从索引 city 取下一个记录的主键 id;
  5. 重复步骤 3、4 直到 city 的值不满足查询条件为止;
  6. 对 sort_buffer 中的数据按照字段 name 做快速排序;
  7. 按照排序结果取前 1000 行返回给客户端。

MySQL 需要 12 个临时文件来做排序的原因

MySQL 将需要排序的数据分成 12 份,每一份单独排序后存在这些临时文件中。然后把这 12 个有序文件再合并成一个有序的大文件。
 

row_id

指定排序的行数据长度后所采用的另一种算法

SET max_length_for_sort_data = 16;

max_length_for_sort_data 是 MySQL 专门控制用于排序的行数据长度的一个参数。

由于行数据长度过短导致排序结果少了 city 和 age 后整个执行的流程

  1. 初始化 sort_buffer,确定放入两个字段,即 name 和 id;
  2. 从索引 city 找到第一个满足 city=‘杭州’ 条件的主键 id;
  3. 到主键 id 索引取出整行,取 name、id 这两个字段,存入 sort_buffer 中;
  4. 从索引 city 取下一个记录的主键 id;
  5. 重复步骤 3、4 直到不满足 city=‘杭州’ 条件位置;
  6. 对 sort_buffer 中的数据按照字段 name 进行排序;
  7. 遍历排序结果,取前 1000 行,并按照 id 的值回到原表中取出 city、name 和 age 三个字段返回客户端。
     

全字段排序 VS rowid 排序

创建 city 和 name 联合索引

alter table t add index city_user(city, name);

city 满足一个值之后name 的值就一定是有序的

  1. 从索引(city,name)找到第一个满足 city=‘杭州’ 条件的主键 id;
  2. 到主键 id 索引取出整行,取 name、city、age 三个字段的值,作为结果集的一部分直接返回;
  3. 从索引(city,name)取下一个记录主键 id;
  4. 重复步骤2、3,直到查到第 1000 条记录,或者是不满足 city=‘杭州’ 条件时循环结束。

创建 city、name 和 age 联合索引

alter table t add index city_user_age(city, name, age);

对于 city 字段值相同的行来说 name 字段的值递增也是递增排序

  1. 从索引(city,name,age)找到第一个满足 city=‘杭州’ 条件的记录,取出其中的 city、name 和 age 这三个字段的值,作为结果集的一部分直接返回;
  2. 从索引(city,name,age)取下一个记录,同样取出这三个字段的值,作为结果集的一部分直接返回;
  3. 重复执行步骤 2,直到查到第 1000 条记录,或者是不满足 city=‘杭州’ 条件时循环结束。

末了

重新总结了一下文中提到的内容:MySQL 里 order by 语句的几种算法流程、每个语句的排序实现、每个语句的执行对系统资源的消耗。

发布了224 篇原创文章 · 获赞 13 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/stevenchen1989/article/details/104936190
59