某些情况中,MySQL可以使用一个索引来满足ORDER BY子句,而不需要额外的排序。
即使ORDER BY不确切匹配索引,只要WHERE子句中的所有未使用的索引部分和所有额外的ORDER BY 列为常数,就可以使用索引。下面的查询使用索引来解决ORDER BY部分:
某些情况中,MySQL可以使用一个索引来满足ORDER BY子句,而不需要额外的排序。
SELECT * FROM t1
ORDER BY key_part1,key_part2,... ;
SELECT * FROM t1
WHERE key_part1=constant
ORDER BY key_part2;
SELECT * FROM t1
ORDER BY key_part1 DESC, key_part2 DESC;
SELECT * FROM t1
WHERE key_part1=1
ORDER BY key_part1 DESC, key_part2 DESC;
在某些情况下,MySQL不能使用索引来解决ORDER BY,尽管它仍然使用索引来找到匹配WHERE子句的行。这些情况包括:
1. 读行匹配WHERE子句的行,如前面所示。
2. 对于每个行,记录构成排序关键字和行位置的一系列值,并且记录查询需要的列。
3. 根据排序关键字排序元组
4. 按排序的顺序检索行,但直接从排序的元组读取需要的列,而不是再一次访问表。
为了避免速度变慢,该优化只用于排序元组中的extra列的总大小不超过max_length_for_sort_data系统变量值的时候。
如果想要增加ORDER BY的速度,首先看是否可以让MySQL使用索引而不是额外的排序阶段。如果不能,可以尝试下面的策略:
1. 增加sort_buffer_size变量的大小。
2. 增加read_rnd_buffer_size变量的大小。
3. 更改tmpdir指向具有大量空闲空间的专用文件系统。
默认情况下,MySQL排序所有GROUP BY col1,col2,…查询的方法如同在查询中指定ORDER BY col1,col2,…。如果显式包括一个包含相同的列的ORDER BY子句,MySQL可以毫不减速地对它进行优化,尽管仍然进行排序。如果查询包括GROUP BY但你想要避免排序结果的消耗,你可以指定ORDER BY NULL禁止排序。例如:
INSERT INTO foo
SELECT a, COUNT(*) FROM bar GROUP BY a ORDER BY NULL;