mysql使用索引扫描做排序_《高性能MySQL》笔记-使用索引扫描来做排序

MySQL有两种方式可以生成有序的结果:通过排序操作;或者按索引顺序扫描;如果EXPLAIN出来的type列的值为“index“,则说明MySQL使用索引扫描来做排序(不要和Extra列的“Using index”搞混淆了)。

扫描索引本身是很快的,因为需要从一条索引记录移动到紧接着的下一条记录。但如果索引不能覆盖查询所需的全部列,那就不得不每扫描一条索引记录就都回表查询一次对应的行。这基本上都是随机I/O,因此按索引顺序读取数据的速度通常比顺序地全表扫描慢,尤其是在I/O密集型的工作负载时。

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

只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向(倒序或正序)都一样时,MySQL才能够使用索引来对结果做排序。如果查询需要关联多张表,则只有当ORDER BY子句引用的字段全部为第一个表时,才能使用索引做排序。OEDER BY子句和查找型查询的限制是一样的:需要满足索引的最左前缀的要求;否则,MySQL都需要执行排序操作,而无法利用索引排序。

有一种情况下ORDER BY子句可以不满足索引的最左前缀的要求,就是前导列为常量的时候。如果WHERE子句或者JOIN子句中对这些列制定了常量,就可以“弥补“索引的不足。

例如,Sakila示例数据库的表rental在列(rental_date,inventory_id,customer_id)上有名为rental_date的索引。

b5036caf3989fb50bb35ee3fa5a45df3.png

MySQL可以使用rental_date索引为下面的查询做排序,从EXPLAIN中可以看到没有出现文件排序(filesort)操作:

0adfc3ad0fe1812b6b091c0615c32736.png

即使OEDER BY子句不满足索引的最左前缀的要求,也可以用于查询排序,这是因为索引的第一列被指定为一个常数。

还有更多可以使用索引做排序的查询示例。下面这个查询可以利用索引排序,是因为查询为索引的第一列提供了常量条件,而使用第二列进行排序,将两列组合在一起,就形成了索引的最左前缀:

… WHERE rental_date = ‘2005-05-25’ ORDER BY inventory_id DESC;

下面这个查询也没有问题,因为ORDER BY使用的两列就是索引的最左前缀:

… WHERE rental_date > ‘2005-05-25’ ORDER BY rental_date, inventory_id;

下面是一些不能使用索引做排序的查询:

下面这个查询使用了两种不同的排序方向,但是索引列都是正序排列的:

… WHERE rental_date = ‘2005-05-25’ ORDER BY inventory_id DESC , customer_id ASC;

下面这个查询的ORDER BY子句中引用了一个不在索引中的列:

… WHERE rental_date = ‘2005-05-25’ ORDER BY inventory_id , staff_id;

下面这个查询的WHERE和ORDER BY中的列无法组合成索引的最左前缀:

… WHERE rental_date = ‘2005-05-25’ ORDER BY customer_id;

下面这个查询在索引列的第一列上是范围条件,所以MySQL无法使用索引的其余列:

… WHERE rental_date = ‘2005-05-25’ ORDER BY inventory_id , customer_id;

这个查询在inventory_id列上有多个等于条件。对于排序来说,这也是一种范围查询:

… WHERE rental_date = ‘2005-05-25’ AND inventory_id IN(1,2) ORDER BY customer_id;

下面这个例子理论上是可以使用索引进行关联排序的,但由于优化器在优化时将film_actor表当做关联的第二张表,所以实际上无法使用索引:

622c9fb05c15e3bc1660ebcd48a6875e.png

使用索引做排序的一个最重要的用法是当查询同时有ORDER BY和LIMIT子句的时候。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值