结论:

  1. mysql(innodb) 选择使用的索引时,有各种的优化选择策略,并不一定会符合我们的预期。而order by主键,这个可能是我们最常用到的一个不符合预期的情境,所以,以后在程序开发中,使用order by时,最好explain一下,看是否使用到了自己预期的索引。
  2. 如果mysql自主选择的索引不符合预期的话,一方面可以通过调整where条件,查询字段等方式进行尝试,使其使用预期的索引,另一方面,则可以使用FORCE INDEX的方式,强制mysql使用我们预期的索引

今天遇到个奇葩的问题,应用主键排序速度奇慢无比,经过不懈的努力,终于找到了问题的原因。

一、错误现象

template表:

by引起慢查询 group mysql order by 导致查询慢_by引起慢查询 group mysql

索引:索引名随便起的,哈哈~

by引起慢查询 group mysql order by 导致查询慢_索引_02

查询语句:

select t.template_id from template t  ORDER BY t.template_id desc

数据库中数据7w多条,查询耗时在8s以上。

二、错误现象分析

首先我们对这条sql执行查询计划:

by引起慢查询 group mysql order by 导致查询慢_by引起慢查询 group mysql_03

发现这条语句应用的索引居然是key_sync_status,而不是主键,这就是问题的关键所在了!

为了进一步确定,再对下面的sql语句执行查询计划:发现使用where条件后,索引变成了主键。

by引起慢查询 group mysql order by 导致查询慢_MySQL_04

通过以上的情况可以看出,MySQL默认的查询(没有where条件),不一定使用主键,由于MySQL的每一条简单查询只应用一个索引,所以,这个时候使用order by 主键,主键的索引功能失效。

三、解决方案

1、order by 索引(where条件中引用的索引)。

2、强制使用主键:FORCE INDEX(PRI),如果想强制使用索引,则用FORCE INDEX(索引名)。

select t.template_id from template t FORCE INDEX(pri) ORDER BY t.template_id desc

四、其他order by 索引失效的原因分析

1、MySQL每天一条简单语句只应用一个索引,所以order by的字段要在索引之中,并且和where条件可以合并成组合索引。

例如:下面情况会应用组合索引。

by引起慢查询 group mysql order by 导致查询慢_by引起慢查询 group mysql_05


2、select的字段,必须是索引字段。(主键查询除外)

例如:下面情况不会应用组合索引。

by引起慢查询 group mysql order by 导致查询慢_MySQL_06

3、如果sql语句为复合语句,包含子查询等,可以把语句分解成简单查询来分析。

以上。