order by 的作用
当使用SELECT语句查询表中的数据时,结果集不按任何顺序进行排序。要对结果集进行排序,请使用ORDER BY
子句。 ORDER BY
子句允许:
- 对单个列或多个列排序结果集。
- 按升序或降序对不同列的结果集进行排序。
下面说明了ORDER BY
子句的语法:
SELECT column1, column2,...
FROM tbl
ORDER BY column1 [ASC|DESC], column2 [ASC|DESC],...
SQL
ASC
表示升序,DESC
表示降序。默认情况下,如果不明确指定ASC
或DESC
,ORDER BY
子句会按照升序对结果集进行排序。
栗子:mysql单个字段降序排序:
select * from table order by id desc;
mysql单个字段升序排序:
select * from table order by id asc;
mysql多个字段排序:
select * from table order by id desc,name desc;
多字字段排序只需要添加多个排序条件,并且每个排序的条件之前用逗号分开。
order by id desc,name desc; 表示先按照id降序排序,再按照name降序排序。
同理:
order by id desc,name asc; 表示先按照id降序排序,再按照name升序排序。
总结:order by 的使用并不复杂,下面可以探究一下其实现原理
order by 的原理
- 利用索引的有序性获取有序数据
- 利用内存/磁盘文件排序获取结果
1) 双路排序:是首先根据相应的条件取出相应的排序字段和可以直接定位行数据的行指针信息,然后在sort buffer 中进行排序。
2)单路排序:是一次性取出满足条件行的所有字段,然后在sort buffer中进行排序。
order by 的优化
-
给order by 字段增加索引,orderby的字段必须在最前面设置
接下来给来说一下orderby什么时候使用索引和什么时候不使用索引的情况
1.使用索引情况- SELECT id from form_entity order by name(给name建立索引)
当select 的字段包含在索引中时,能利用到索引排序功能,进行覆盖索引扫描,使用select * 则不能利用覆盖索引扫描且由于where语句没有具体条件MySQL选择了全表扫描且进行了排序操作。 - SELECT * from form_entity where name =’123’ and category_id=’1’ order by comment desc(name,comment建立复合索引)
组合索引中的一部分做等值查询 ,另一部分作为排序字段 - SELECT comment from form_entity group by name,comment order by name (name,comment建立复合索引)
2.不使用索引情况
- SELECT id,comment from form_entity order by name(给name建立索引,comment没有索引)
- SELECT * from form_entity order by name(给name设置索引)
- SELECT * from form_entity order by name desc,comment desc(name,comment建立复合索引)
- SELECT * from form_entity where comment =’123’ order by name desc(name,comment建立复合索引)
- SELECT name from form_entity where category_id =’123’ order by name desc,comment desc(name,comment建立复合索引,category_id独立索引)
当查询条件使用了与order by不同的索引,但排序字段是另一个联合索引的非连续部分 - SELECT comment from form_entity group by name order by name ,comment(name,comment建立复合索引)
- 返回数据量过大也会不使用索引
- 排序非驱动表不会走索引
- order by 字段使用了表达式
- SELECT id from form_entity order by name(给name建立索引)
-
去掉不必要的返回字段
- 增大 sort_buffer_size 参数设置