mysql的order by 排序

MySQL排序优化
本文详细介绍了MySQL中的两种排序方式:indexsort和filesort,并探讨了它们的工作原理、使用条件及优化方法。

mysql 的排序

1.indexsort  利用有序索引获取有序数据

原理:

我们知道,mysql的基础数据结构是B+树,任何的一个表都是一颗B+树,你在表上建的索引也是一颗B+树,B+树的特别是在叶子节点上是有序,且前一个节点存在指向相邻节点的指针。

那么在写SQL中的ORDER BY语句时候,若是ORDER BY的条件和返回的数据都在一颗树上,那么就可以利用B+树自身的特点来天然排序了,自然效率会比较高。

 

使用条件:

1)查询的WHERE子句和ORDER BY子句中查询的字段在同一颗索引树上,

2)ORDER BY 字段的顺序是跟建立索引的顺序是一致的。

3)查询的字段也在同一颗索引树

以上三个条件必须同时满足 

 

2.filesort 文件排序

原理:

这里的文件排序并不是字面那表示的意思,利用了磁盘IO来进行排序,不过是优化器告诉你,进行了一个排序操作,具体排序的地方还是内存,相对应的参数是sort_buffer_size 设定的大小

1)filesort不一定会产生临时表

2)filesort 与临时表数据写入磁盘是没有任何直接联系

 

使用情景:

任何非索引排序的场景下

 

 

3.实战:

CREATE TABLE `A_index` (

`c1` INT(11) NOT NULL AUTO_INCREMENT ,

`c2` SMALLINT(2)  ,

`c3` VARCHAR(16)  ,

`c4` VARCHAR(16)  ,

`c5` VARCHAR(16)  ,

PRIMARY KEY  (`c1`),

KEY `c2_ind` (`c2`),

KEY `c3_c4_c5_ind` (`c3`,`c4`,`c5`)

) ENGINE=INNODB DEFAULT CHARSET=utf8

 

1)查询的字段和ORDER BY 字段在同一个索引树中:

mysql> EXPLAIN SELECT c3 FROM A_index ORDER BY c3 ,c4 ,c5 ;

+----+-------------+---------+-------+---------------+--------------+---------+------+------+-------------+

| id | select_type | table   | type  | possible_keys | key          | key_len | ref  | rows | Extra       |

+----+-------------+---------+-------+---------------+--------------+---------+------+------+-------------+

|  1 | SIMPLE      | A_index | index | NULL          | c3_c4_c5_ind | 153     | NULL |    1 | Using index |

+----+-------------+---------+-------+---------------+--------------+---------+------+------+-------------+

1 row in set (0.02 sec)

 

2)查询的字段和where 及 order by 中的字段在同一颗树中

mysql> EXPLAIN SELECT c3 FROM A_index where c3="1" ORDER BY c3 ,c4 ,c5 ;

+----+-------------+---------+------+---------------+--------------+---------+-------+------+--------------------------+

| id | select_type | table   | type | possible_keys | key          | key_len | ref   | rows | Extra                    |

+----+-------------+---------+------+---------------+--------------+---------+-------+------+--------------------------+

|  1 | SIMPLE      | A_index | ref  | c3_c4_c5_ind  | c3_c4_c5_ind | 51      | const |    1 | Using where; Using index |

+----+-------------+---------+------+---------------+--------------+---------+-------+------+--------------------------+

1 row in set (0.00 sec)

对于上面的差别是做了一次回表

 

3)where 及 order by 中的字段不在同一颗树中

mysql> EXPLAIN SELECT c3 FROM A_index where c2=1 ORDER BY c3 ,c4 ,c5 ;

+----+-------------+---------+------+---------------+--------+---------+-------+------+-----------------------------+

| id | select_type | table   | type | possible_keys | key    | key_len | ref   | rows | Extra                       |

+----+-------------+---------+------+---------------+--------+---------+-------+------+-----------------------------+

|  1 | SIMPLE      | A_index | ref  | c2_ind        | c2_ind | 3       | const |    1 | Using where; Using filesort |

+----+-------------+---------+------+---------------+--------+---------+-------+------+-----------------------------+

1 row in set (0.01 sec)

在两颗索引树中后,就走的是filesort了。

 

4)查询的字段和ORDER BY 字段不在同一个索引树中:

mysql> EXPLAIN SELECT c2 FROM A_index  ORDER BY c3 ,c4 ,c5 ;

+----+-------------+---------+------+---------------+------+---------+------+------+----------------+

| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows | Extra          |

+----+-------------+---------+------+---------------+------+---------+------+------+----------------+

|  1 | SIMPLE      | A_index | ALL  | NULL          | NULL | NULL    | NULL |    1 | Using filesort |

+----+-------------+---------+------+---------------+------+---------+------+------+----------------+

1 row in set (0.00 sec)

 

 

5)查询的字段和ORDER BY 字段在同一个索引树中,但是order by 顺序不同

mysql> EXPLAIN SELECT c3 FROM A_index  ORDER BY c4 , c3  ,c5 ;

+----+-------------+---------+-------+---------------+--------------+---------+------+------+-----------------------------+

| id | select_type | table   | type  | possible_keys | key          | key_len | ref  | rows | Extra                       |

+----+-------------+---------+-------+---------------+--------------+---------+------+------+-----------------------------+

|  1 | SIMPLE      | A_index | index | NULL          | c3_c4_c5_ind | 153     | NULL |    1 | Using index; Using filesort |

+----+-------------+---------+-------+---------------+--------------+---------+------+------+-----------------------------+

1 row in set (0.00 sec)

看到排序使用的是filesort,对于c3的查找用的是索引

 

 

4.优化filesort

从上面的索引排序使用限制上可以看出,我们大部分的业务场景应该是在filesort下,那么就该想着如何优化filesort。

filesort的两种排序算法:

双路排序

1)取出所有排序的字段及对应行数据的指针信息(指向具体的叶子节点数据)

2)在内存中进行排序

3)再通过指针取得具体的数据

 

单路排序

1)去除所有排序的字段及所有行信息

2)在内存中进行排序

 

两种的差别在于第一种需要两次磁盘IO,而第二种只需要一次,但第二种需要更大的内存开销。

 

优化器如何选择主要是根据 max_length_for_sort_data 系统参数设置的大小

mysql> show variables like '%max_length%';

+--------------------------+-------+

| Variable_name            | Value |

+--------------------------+-------+

| max_length_for_sort_data | 1024  |

+--------------------------+-------+

1 row in set (0.00 sec)

 

若是查询出来的数据大小 > max_length_for_sort_data ,那么使用双路排序

若是查询出来的数据大小 < max_length_for_sort_data ,那么使用单路排序

 

 

### MySQLORDER BY 排序方法及使用示例 在 MySQL 中,`ORDER BY` 子句用于对查询结果集按照一个或多个列进行排序。默认情况下,排序方式为升序(ASC),但也可以通过指定 `DESC` 关键字实现降序排序。 #### 基本语法 ```sql SELECT column1, column2, ... FROM table_name ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...; ``` #### 简单排序示例 假设有一个名为 `order_test` 的表,其中包含一个 `score` 字段。要按照 `score` 升序排列所有记录,可以使用以下 SQL 语句: ```sql SELECT * FROM order_test ORDER BY score ASC; ``` 此查询将返回 `order_test` 表中的所有记录,并按 `score` 字段的值从小到大排序[^1]。 #### 多字段排序 如果需要根据多个字段进行排序,可以在 `ORDER BY` 后面列出这些字段,并为每个字段指定排序方向。例如,先按 `province` 升序,再按 `city` 降序: ```sql SELECT * FROM order_test ORDER BY province ASC, city DESC; ``` 在这种情况下,MySQL 会首先按照 `province` 字段的拼音首字母 ASCII 规则进行排序。如果多个记录的 `province` 相同,则进一步按照 `city` 字段的拼音首字母进行降序排列[^3]。 #### 使用索引优化排序 当处理大量数据时,为了提高排序效率,可以考虑为经常用于排序字段添加索引。如果查询能够利用索引完成排序MySQL 将不会执行额外的排序操作,从而减少资源消耗。例如,如果 `city` 和 `name` 字段已经被包含在一个覆盖索引中,那么以下查询可以直接使用索引而无需额外排序: ```sql SELECT city, name FROM order_test ORDER BY city, name; ``` 在这种情况下,查询的执行计划中的 `Extra` 字段会显示 `Using index`,表明没有发生 `filesort` 操作[^4]。 #### 降序排序示例 若希望按某个字段进行降序排序,可以使用 `DESC` 关键字。例如,要按 `score` 字段降序排列: ```sql SELECT * FROM order_test ORDER BY score DESC; ``` 此查询将返回 `order_test` 表中的所有记录,并按 `score` 字段的值从大到小排序[^1]。 #### 结合 WHERE 条件使用 `ORDER BY` 通常 `WHERE` 子句一起使用,以先筛选出符合条件的数据,再对其进行排序。例如: ```sql SELECT * FROM order_test WHERE province = 'Beijing' ORDER BY score DESC; ``` 此查询将仅返回 `province` 为 'Beijing' 的记录,并按 `score` 字段降序排列。 #### 性能注意事项 - **索引使用**:确保排序字段上有合适的索引,以避免 `filesort` 操作,提高查询性能[^2]。 - **避免不必要的排序**:如果查询结果不需要排序,应省略 `ORDER BY` 子句,以减少数据库负担。 - **合理选择排序字段**:尽量选择区分度高的字段进行排序,以提高排序效率。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值