你真的懂mysql中order by吗

在写sql语句查询的时候,很多情况都需要将目标数据按照某个字段进行排序再返回,在sql中通常就用order by来完成排序,那么,mysql内部是如何完成排序的呢,除了order by 之外,还有更好的排序方式吗?

一、order by实现方式

首先,要知道mysql会为每个线程分配一部分内存空间用来专门做排序,名字就叫做“sort_buffer”。

第一种情况:

1、如果目标数据单条记录数据量不大的情况下,mysql会将每行的数据全字段的放到‘sort_buffer’中,如果“sort_buffer”空间不够的话,会从磁盘中建立临时文件帮助做排序

这种情况可以叫做全字段排序

第二种情况:

2、如果目标数据单条记录数据量达到一定阈值的情况下,mysql就会仅将每行的数据的排序字段及主键放到‘sort_buffer’中,如果“sort_buffer”空间不够的话,会从磁盘中建立临时文件帮助做排序。

这种情况就可以叫做rowid排序。rowid排序完成之后,不能直接返回,因为此时只有两个字段,需要拿着主键id再去查一次数据表,所以rowid这种方式的排序要扫描的行数更多

而决定用哪种排序方式的就是max_length_for_sort_data参数,这个参数就是判断单行数据大小是否达到阈值的参数,可以通过设置max_length_for_sort_data来调整这个阈值。

例如:SET max_length_for_sort_data =32;

整个排序的执行流程:

1、初始化sort_buffer,确定用哪种排序方式;

2、查询出目标数据;

3、将目标数据全字段(或者排序字段及主键id)存到sort_buffer(必要的话,还有磁盘的临时文件)中;

4、对sort_buffer中的数据按照排序字段进行快速排序;

5、返回结果集(全字段排序);

5、遍历排序结果,并按照主键id的值回到原表中取出全字段数据返回;(rowid排序)

二、代替order by的方式

由上可知,排序是一个成本较高的操作,可能还会涉及到磁盘访问,那有没有一种更加搞笑的排序呢?当然有,还记得联合索引吗,联合索引在建立的时候,就已经做好了排序;比如name_age联合索引,在同一个name下,age的值就一定是排列有序的,因此就可以通过这个特点来进行一些sql上的优化,不过,这种情况并不多见,该用order by还是要用的;

### MYSQL 中 GROUP BYORDER BY 的结合使用 在 MySQL 查询中,`GROUP BY` 主要用于对数据进行分组操作,而 `ORDER BY` 则负责对结果集进行排序。两者可以在同一个查询语句中同时使用,但在实际应用中有一定的语法要求和注意事项。 #### 基本语法结构 当需要同时使用 `GROUP BY` 和 `ORDER BY` 时,基本的 SQL 语法如下所示: ```sql SELECT column, aggregate_function(column), ... FROM table_name [WHERE conditions] GROUP BY group_by_expression [HAVING having_conditions] [ORDER BY order_columns]; ``` 在此语法中,`GROUP BY` 子句定义了如何对记录进行分组,而 `ORDER BY` 定义了最终输出的结果集中各组之间的顺序[^1]。 #### 使用场景分析 如果希望先按某些字段分组再对这些分组后的结果进行排序,则可以直接将 `ORDER BY` 放置在查询的最后一部分。例如,在员工表中统计各部门工资总和并按照部门编号升序排列: ```sql SELECT department_id, SUM(salary) AS total_salary FROM employees GROUP BY department_id ORDER BY department_id ASC; ``` 此查询会返回每个部门及其对应薪资总额,并确保结果依据部门 ID 排列有序[^1]。 然而需要注意的是,当存在嵌套子查询或者复杂逻辑处理时(比如引用提到的情况),为了实现特定需求如获取每组内的前几条记录后再做进一步汇总展示,则需采用更复杂的写法来满足业务需求[^2]。 对于这种情况下的具体实现方式可参照下面例子: 假设有一个名为 index_test 表包含多个字段其中含有年龄(age),所属部门(departmentid)等信息;现在目标是从该表格里选取最近五位最年长者之后基于他们所在的部门重新整理成唯一代表形式呈现出来即只保留第一个出现的人作为代表人物之一。 ```sql SELECT t.* FROM ( SELECT * FROM `index_test` ORDER BY age DESC LIMIT 5 ) t GROUP BY DEPARTMENTID ORDER BY DEPARTMENTID; ``` 这里通过创建临时视图t实现了初步筛选过程——选出五个年纪最大的个体;随后利用外部层面对这个缩小范围的数据集合执行去重动作(以departmentid为准),最后再次指定整体输出次序保持一致以便观察方便[^2]。 #### 注意事项 尽管可以组合运用这两个功能强大的工具,但也应注意到一些潜在陷阱或限制条件: - 如果没有明确指出哪些列为聚合函数参数的话可能会引发错误提示因为SQL标准规定非聚集项都得参与grouping key之中除非启用了特殊模式允许这种例外情况发生。 - 当涉及到大量数据运算时候性能开销较大因此建议合理设计索引来优化访问路径从而提升效率减少资源消耗。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值