16“order by”是怎么工作笔记

order by工作原理

author:陈镇坤27

创建时间:2021年11月18日02:25:53

编辑时间:2021年11月18日16:29:43、2021年11月19日14:45:56、2021年12月9日11:31:28

转载请注明出处


——————————————————————————————.

问:查询语句进行排序,会用到哪几种排序规则?

答:如果排序字段有索引,则直接查出即可,否则执行全字段排序或rowId排序。

全字段排序

问:什么是全字段排序?什么情况发生。

答:SQL查询语句的排序,需要查询的所有字段参与。

当查询语句需要排序,排序字段上没有索引可以充分利用并且查询的数据行长度不超过设置值时,进行全字段排序。

问:怎么判断是一个查询语句是全字段排序。

答:排序无法利用上索引,并且查询的行长度不超过设置的值时,会是全字段排序。

查询全字段排序允许的最长行数据长度命令为:

show variables like  '%max_length_for_sort_data%';

问:全字段排序是如何执行的?

答:MySQL会给每个查询线程在server层分配一块用于排序的内存,称为“sort_buffer”(默认256k大小)。

首先,在server层初始化sort_buffer,并预存需要查询的列字段。

然后,每次从主键索引树中获取行数据时,将行对应目标字段值存放到sort_buffer当中。

之后,符合条件的索引树的行数据检索完毕后,开始对sort_buffer进行快速排序(采用快速排序算法)

最后将排序结果的前N行返回给客户端。

问:怎么查看全字段排序的详细过程?

答:

-- 先开启优化追踪表
set optimizer_trace = 'enabled=on'


-- 执行查询命令
XXX

-- 查询优化追踪表
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G

下图截选日志打印的部分结果:

在这里插入图片描述

其中,examined_rows表示需要检查的总数据量(不是指sort_buffer有多少数据),number_or_temp_files表示外部文件数量,主要通是当参与排序的数据大小超过sort_buffer_size,要借助磁盘进行归并排序——拆分多个文件,各文件进行排序,再全部整合起来排序。

PS:

show variables like '%sort_buffer_size%';
+-------------------------+---------+
| Variable_name           | Value   |
+-------------------------+---------+
| innodb_sort_buffer_size | 1048576 |
| myisam_sort_buffer_size | 8388608 |
| sort_buffer_size        | 262144  |
+-------------------------+---------+

可以检索Innodb_rows_read来判断Innodb扫描的行数(注意:由于OPTIMIZER_TRACE查询本身是从表(磁盘临时表)中获取数据,加上internal_tmp_disk_storage_engine默认引擎是Innodb,那得到的结果会+1,解决方法是将默认临时表引擎设置为MyINSAM引擎)

select VARIABLE_VALUE into @a from  performance_schema.session_status where variable_name = 'Innodb_rows_read';

rowid排序

问:什么是rowId排序?

答:MySQL在sort_buffer中初始化参与排序的字段和主键Id,然后在引擎返回的行数据中,只取排序的字段和主键值存入sort_buffer,等所有满足条件的数据存入完毕后,再对排序字段进行快速排序,并返回语句需要(limit)的Id数据,然后依次根据Id再查主键索引树,并将id对应的数据直接返回给客户端(此时不需要再将数据缓存到内存)。

问:什么时候MySQL会采用rowId排序,为什么?

答:MySQL当判定需要参与排序的字段长超过设置值时,会采用rowid排序。原因是如果参与排序的全字段总数据量过大,则需要的外部文件就越多,排序效果便越差。比起更多的外部磁盘文件排序,通过减少外部磁盘文件,增加回表次数的排序方式性能可能会更好一些。

全字段排序和rowid排序

问:MySQL选择排序的策略是什么?

答:内存足够,则尽量使用内存。显然,在内存充足情况下,直接全字段排序效果最好,不需要回表。但是当内存不足时,MySQL要权衡更多的磁盘文件排序和更多的回表查询数据,哪个性能损耗更多,而其根据是由max_length_for_sort_data的值来判断的。

当然,如果排序的字段有索引的话,则查询的数据从最初便是有序的,此时不再需要建立临时表来进行排序。

问:在排序上,有什么索引优化建议呢?

答:若查询有筛选条件,且筛选条件有索引时,可以建联合索引,将排序字段设为后面的联合属性之一。

问:使用排序时,explain怎么看?有什么额外补充吗?

答:如果使用了临时表进行排序,则extra会提示using filesort。using index condition是使用了索引下推。using index是使用了覆盖索引,此时不会有索引下推,取而代之是using where——使用了筛选。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

陈镇坤27

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值