MySQL 学习:ORDER BY 优化

在某些情况下,MySQL 可以使用索引优化排序,从而避免额外的排序操作。本文主要记录 MySQL 何时可以使用索引优化排序以及何时无法使用索引优化排序的几种情况。

环境说明

  • 应用:mysql-boost-5.7.20.tar.gz

索引优化排序

由于 B-TREE 索引数据结构的特性,索引本身就是有序存放的。当索引满足排序条件时,MySQL 不需要进行额外的排序操作,只需找到指定索引树的起始叶子节点之后,按顺序向右或向左读取读取叶子节点即可。

以下几种情况,MySQL 可以使用索引优化排序,无需进行额外的排序操作:

# 无 WHERE 从句时,在 ORDER BY 从句中,使用指定一个索引或指定一个多列索引的前缀
SELECT * FROM t1
  ORDER BY key_part1, key_part2;

# 在 WHERE 从句中,使用多列索引的前缀过滤行记录,同时,在 ORDER BY 从句中,使用该多列索引的连续后缀排序
SELECT * FROM t1
  WHERE key_part1 = constant
  ORDER BY key_part2;

# 在 ORDER BY 从句中,多列索引的每个字段的排序方向是一致的
SELECT * FROM t1
  ORDER BY key_part1 DESC, key_part2 DESC;

# 注意!!!虽然,创建索引的语法支持指定索引字段的排序方向。但是,在 MySQL 8.0 之前的版本,指定排序方向是无效的,MySQL 默认会使用升序排序索引字段。

# 在 WHERE 从句中,使用多列索引的前缀过滤行记录(必须等值匹配),在 ORDER BY 从句中,完整使用该索引排序
SELECT * FROM t1
  WHERE key_part1 = 1
  ORDER BY key_part1 DESC, key_part2 DESC;

# 在 WHERE 从句中,使用多列索引的前缀过滤行记录,在 ORDER BY 从句中,使用该索引的同一个前缀排序
SELECT * FROM t1
  WHERE key_part1 > constant
  ORDER BY key_part1 ASC;

SELECT * FROM t1
  WHERE key_part1 < constant
  ORDER BY key_part1 DESC;

SELECT * FROM t1
  WHERE key_part1 = constant1 AND key_part2 > constant2
  ORDER BY key_part2;

无法使用索引优化排序

以下几种情况,MySQL 无法通过索引优化排序:

# 在 ORDER BY 从句中,使用多个索引
SELECT * FROM t1 ORDER BY key1, key2;

# 在 ORDER BY 从句中,使用多列索引,但多列索引的字段不是连续的
SELECT * FROM t1 WHERE key2=constant ORDER BY key_part1, key_part3;

# 在 ORDER BY 从句中,多列索引的每个字段排序方向不同
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;

# 在 ORDER BY 从句中,使用与 WHERE 从句不同的索引
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;

# 在 ORDER BY 从句中,对索引字段进行运算
SELECT * FROM t1 ORDER BY ABS(key);
SELECT * FROM t1 ORDER BY -key;

# 多表关联查询时,在 ORDER BY 从句中的字段不是来自驱动表

# ORDER BY 从句的表达式与 GROUP BY 从句的表达式不同
SELECT * FROM t1 GROUP BY key_part1, key_part2 ORDER BY key_part1 DESC;

# 字段数据类型为 CHAR(20),对该字段的前 10 个字节建立索引。
# 在 ORDER BY 从句中,使用该索引,由于无法区分超过 10 个字节的字段值,因此,需要额外的排序操作。

# 索引本身不是有序的。
# 例如:HASH 索引本身就是无序的,无法满足排序。

参考资料

添加评论

验证码: