《MySQL——order by逻辑(全字段排序与rowid排序)》

创建一个表,然后使用查询语句:
查询城市是“杭州”的所有人名字,并且按照姓名排序返回前 1000 个人的姓名、年龄

create table 't' (
	'id' int(11) not null,
	'city' vachar(16) not null,
	'name' vachar(16) not null,
	'age' vachar(16) 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字段上加上索引

假设满足city = '杭州’条件的行是从ID_X到ID_(X+N)的这些记录。
执行流程:
1、初始化sort_buffer,确定放入name、city、age三个字段;
2、从索引city找到第一个满足city = '杭州’条件的主键id,也就是ID_X;
3、到主键id索引取出整行,取name、city、age三个字段值,存入sort_buffer;
4、从索引city取下一个记录的主键id;
5、重复step3、4直到city的值不满足查询条件为止,对应的ID(X+N);
6、对sort_buffer中的数据按照字段name做快速排序
7、按照排序结果取前1000行返回给客户端

tip:sort_buffer是MySQL分配给每个线程用于排序的内存。
sort_buffer是MySQL分配给每个线程用于排序的内存。sort_buffer_size是sort_buffer的大小,如果要排序的数据量小于sort_buffer_size,排序就在内存中完成,如果排序数据量过大,就得使用磁盘临时文件辅助排序。外部排序一般使用归并排序算法。

rowid 排序

全字段排序方法缺点:单行大的话占用内存空间。
通过修改MySQL中专门控制用于排序的行数据的长度的一个参数。意思是,如果单行的长度超过这个值,就会换一种算法

SET max_length_for_sort_data = 16;

新的算法只会讲排序的列(name字段)和主键id放入sort_buffer;
所以排序的结果就少了city和age字段值,不能直接返回。
执行流程如下:
1、初始化sort_buffer,确定放入name和id字段;
2、从city索引中找到第一个满足city = '杭州’条件的主键id,也就是图中的ID_X;
3、到主键id索引取出整行,取name、id两个字段,存入sort_buffer;
4、从city索引取下一条记录的主键id
5、重复step3、4直到不满足city = '杭州’为止
6、对sort_buffer中的数据按照字段name进行排序
7、遍历排序结果,取前1000行,并按照id的值回到原表中取出city、name、age三个字段返回给客户端

rowid 方式和全字段方式一样,需要先把查询到的结果全部放在内存或硬盘中,再使用相关算法进行排序。而排序后由于没有保存所需的字段,需要按顺序使用主键再从索引树上查询,查到一个就返回一个,而不用把所有内容查完放到内存上再一并返回。

两者比较

全字段排序
rowid 排序

如果担心排序内存太小,会影响排序效率,才会采用rowid排序算法,这样排序过程中依次可以排序更多行,但是需要再回到原表去取数据。
如果MySQL认为内存足够大,会优先选择全字段排序,把需要的字段都放到sort_buffer中,这样排序后就会直接从内存里面返回查询结果了,不用再回到原表中取数据。

对于InnoDB,rowid排序会要求回表多造成磁盘读,因此不会被优先选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

拾牙慧者

欢迎请作者喝奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值