MySQL 使用索引扫描来做排序

September 14, 2016 3:54 PM

声明

文章内容出自《高性能Mysql第三版》

MySQL有两种方式可以生成有序的结果:通过排序操作;或者按索引顺序扫描 如果explain出来的type列的值为index,则说明MySQL使用了索引来扫描做排序

MySQL可以使用同一个索引即满足排序,有用于查找行。所以如果可以,设计索引是应该尽可能地同时满足这两种任务。这样是最好的。

只有当所以的列顺序和order by字句顺序完全一致,并所有列的排序方向(倒序或者正序)都一样时,MySQL才能够使用索引来对结果做排序

如果查询需要关联多张表,则只有当order by字句引用的字段全为一个表时,才能使用索引做排序

order by 字句和查找型查询的限制是一样的。需要满足索引最左前缀的要求。否则,MySQL都需要执行排序操作。而无法使用索引来排序

有一种情况下order by字句可以不满足索引的最左索引的要求,就是前导列为常量的时候。如果where字句或者join字句中对这些列指定了常量。就可以弥补索引的不足

例如: demo表的索引index1(a,b,c);

select id,name from demo where a='10' order by b,c; 
/* 这时候,因为a指定的是一个常量,所以就可以是用索引index1·来排序,同理order by b 也是可以是用索引的 */

select id,name from demo where a>10 order by a,b;
/* 这时候也可以使用索引来排序 */
 
/* 下列的SQL则无法是用索引来排序:*/

select id,name from demo where a=10 order by b DESC,c ACS 
/* 使用了两种不同的排序方式*/ 

select id,name from demo where a=10 order b,group_id
/*因为排序中使用了一个不再索引的列*/

select id,name from demo where  a=10 order by c 
/*无法组合成最左索引 */

select id,name from demo where a>10 order by b,c
/*因为第一列是范围条件*/

select id,name from demo where a=10 and b in(1,2,3) order by c   
/*因为b使用了in 也属于范围查询,所以无法使用索引   */