MySQL高性能的索引策略(四)
使用索引扫描来做排序
mysql有两种方式可以生成有序的结果:通过排序操作;或者通过索引顺序扫描;如果explain出来的type列的值为index,则说明mysql使用了索引扫描来做排序(不要和Extra 列的“using index”搞混淆了)。
扫描索引本身是很快的,因为只需从一条记录移动到紧接着的下一条记录。但如果索引不能覆盖查询所需的全部列,那就不得不每扫描一条索引记录就得回表查询一次对应的行。这基本上都是随机IO,因此按索引顺序读取数据的速度通常比顺序的全表扫描慢,尤其是在IO密集型的工作负载时。
mysql可以使用同一个索引既满足排序,又用于查找行。因此如果可能,设计索引时应该尽可能的满足这两种任务。
只有当索引的列的顺序和order by子句的顺序完全一致,并且所有列的排序方向(倒序和正序)都一样时,mysql才能使用索引来对结果做排序。
如果查询需要关联多张表,则只有order by子句引用的字段全部为第一个表时,才能使用索引来做排序。
order by子句和查找型查询的限制时一样的:需要满足索引的最左前缀的要求;否则,mysql都需要执行排序操作,而无法利用索引排序。
有一种情况下order by子句可以不满足索引的最左前缀要求,就是前导列为常量的时候。
如果where子句或者join子句中对这些列指定了常量,就可以弥补索引的不足。
> explain
select id from article where title = 'hello world' order by shortName asc
******************** 1. row *********************
id: 1
select_type: SIMPLE
table: article
type: ref
possible_keys: idx_short_name_title
key: idx_short_name_title
key_len: 257
ref: const
rows: 5
Extra: Using where; Using index
1 rows in set
就如上面这个sql语句一样,虽然order by子句不能满足索引的最左前缀的要求,也可以用于查询排序,这是因为索引的第一列被指定为一个常数。就是 title = 'hello world';
就如上面的结果显示的那样,在explain的结果中,没有出现using filesort。
我们来对照一下区别,
> explain
select id from article order by title asc
******************** 1. row *********************
id: 1
select_type: SIMPLE
table: article
type: index
possible_keys:
key: idx_short_name_title
key_len: 514
ref:
rows: 5
Extra: Using index
1 rows in set
order by的列和索引的列的顺序一致。没有出现using filesort。
> explain
select id from article order by shortName asc
******************** 1. row *********************
id: 1
select_type: SIMPLE
table: article
type: index
possible_keys:
key: idx_short_name_title
key_len: 514
ref:
rows: 5
Extra: Using index; Using filesort
1 rows in set
order by的列的顺序和索引列的顺序不一致,所以出现using filesort。
但是当查询的列不能全部被索引覆盖时,虽然指定索引列的前导列为常量,order by列的顺序和索引列其余的一致,但也是会出现using filesort。
> explain
select id,totalView from article where title = 'hello world' order by shortName asc
******************** 1. row *********************
id: 1
select_type: SIMPLE
table: article
type: ALL
possible_keys: idx_short_name_title
key:
key_len:
ref:
rows: 5
Extra: Using where; Using filesort
1 rows in set
==========END==========
来源:oschina
链接:https://my.oschina.net/u/1469576/blog/495856