MySQL 使用索引扫描进行排序

 更新时间:2021年06月18日 10:53:19   作者:临时营地  
mysql可以使用同一个索引既满足排序,又用于查找行,因此,如果可能,设计索引时应该尽可能地同时满足这两种任务,这样是最好的。本文将介绍如何利用索引来进行排序

安装sakila

我们将会使用MySQL示例数据库sakila来进行sql的演示和讲解 dev.mysql.com/doc/sakila/…

索引扫描排序

MySQL有两种方式可以生成有序的结果:通过排序操作﹔或者按索引顺序扫描﹔如果EXPLAIN出来的type列的值为“index”,则说明MySQL使用了索引扫描来做排序。
扫描索引本身是很快的,因为只需要从一条索引记录移动到紧接着的下一条记录。但如果索引不能覆盖查询所需的全部列,那就不得不每扫描一条索引记录就都回表查询一次对应的行。这基本上都是随机I/O,因此按索引顺序读取数据的速度通常要比顺序地全表扫描慢,尤其是在IO密集型的工作负载时。此时可能就会用全表扫描而不是按索引查找了。
如果可能,设计索引时应该尽可能地同时满足排序和查找行。
只有当索引的列顺序和0RDER BY子句的顺序完全一致,并且所有列的排序方向(倒序或正序)都一样时,MySQL才能够使用索引来对结果做排序。如果查询需要关联多张表,则只有当ORDER BY子句引用的字段全部为第一个表时,才能使用索引做排序。ORDER BY子句和查找型查询的限制是一样的:需要满足索引的最左前缀的要求﹔否则,MySQL都需要执行排序操作(filesort),而无法利用索引排序。

表结构

我们将使用rental这个表来进行讲解

CREATE TABLE `rental` (
  
  UNIQUE KEY `rental_date` (`rental_date`,`inventory_id`,`customer_id`),
  KEY `idx_fk_inventory_id` (`inventory_id`),
  KEY `idx_fk_customer_id` (`customer_id`),
  KEY `idx_fk_staff_id` (`staff_id`),
  
) ENGINE=InnoDB AUTO_INCREMENT=16050 DEFAULT CHARSET=utf8mb4;

查看Extra 中是否出现Using filesort(MySQL中无法利用索引完成的排序操作称为“文件排序”)当我们试图对一个没有索引的字段进行排序时,就是filesort。虽然里面有个file,但它跟文件没有任何关系,实际上是内部的一个快速排序

可以使用索引扫描来做排序的情况

补足前导列

有一种情况下ORDER BY子句可以不满足索引的最左前缀的要求,就是前导列为常量的时候。如果WHERE子句或者JOIN子句中对这些列指定了常量,就可以“弥补”索引的不足。 我们使用Sakila数据库来测试一下

可以看到

书上的Extra写的是Using where,而我执行的时候是Using index condition ,原因是高性能MySQL中使用的版本是5.5,5.6版本中的索引条件推送(index condition pushdown)还处于未正式发布阶段呢。这里没有filesort的原因是因为有个rental_date = '2005-05-25'的常量条件,相当于将索引的第一列补足了,这样就符合了索引的最左前缀要求。

order by 中只包含一种排序

SELECT rental_id, staff_id FROM sakila.rental WHERE rental_date = '2005-05-25' ORDER BY  inventory_id desc

可以看到

需要注意这一条,在书中使用的的条件是rental_date>'2005-05-25'

WHERE rental_date > '2005-05-25' ORDER BY rental_date, inventory_id

此时无法使用索引排序而是直接全表扫描做了个排序,原因是因为返回数据的条数过多,用索引查询此时已经不划算了

需要注意这里的解释里面的rows并不准确,只是一个估算值,实际上按这个条件查询有16036条数据 要想解决这个问题,就需要加上limit

SELECT rental_id, staff_id FROM sakila.rental WHERE rental_date > '2005-05-25' ORDER BY rental_date, inventory_id limit 0,10

对应的执行计划

可以看到使用了索引

无法使用索引扫描的情况

查询条件中包含不同排序方向

SELECT rental_id, staff_id FROM sakila.rental WHERE rental_date = '2005-05-25' ORDER BY  inventory_id desc,customer_id asc

索引中两列都是正序,现在order by 中一列正序一列倒序就得二次排序了。

查询条件中引用不在索引中的列

SELECT rental_id, staff_id FROM sakila.rental WHERE rental_date ='2005-08-23 21:01:09' ORDER BY  inventory_id ,staff_id

无法组合最左前缀时

SELECT rental_id, staff_id FROM sakila.rental WHERE rental_date ='2005-08-23 21:01:09' ORDER BY  customer_id

第一列是查询范围时

SELECT rental_id, staff_id FROM sakila.rental WHERE rental_date > '2005-08-22' ORDER BY  inventory_id,customer_id

where中有多个等于条件

SELECT rental_id, staff_id FROM sakila.rental WHERE rental_date ='2005-08-23 21:01:09' and inventory_id in(1,2)  ORDER BY  customer_id

简单来说就是不符合索引最左前缀的就会进行一次排序。

总结

今天我们讲解了MySQL中的索引扫描排序,明天我们还将继续介绍其他建立高性能索引的方法,敬请期待,下篇再见!

以上就是MySQL 索引扫描的简单使用的详细内容,更多关于MySQL 索引扫描排序的资料请关注脚本之家其它相关文章!

相关文章

  • 浅谈为什么MySQL不建议delete删除数据

    浅谈为什么MySQL不建议delete删除数据

    这篇文章主要介绍了浅谈为什么MySQL不建议delete删除数据,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Win7下mysql5.5安装图文教程

    Win7下mysql5.5安装图文教程

    这篇文章主要为大家详细介绍了Win7下mysql5.5安装的图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • MySQL 隔离数据列和前缀索引的使用总结

    MySQL 隔离数据列和前缀索引的使用总结

    正确地创建和使用索引对于查询性能十分重要。由于存在很多种特殊场景的优化和行为,因此有很多种方式去有效选择和使用索引。因此,决定如何使用索引这一项技能是需要经验和时间的积累去培养的。以下会介绍一些如何有效使用索引的方法。
    2021-05-05
  • mysql修改自增主键数值无效的问题及解决

    mysql修改自增主键数值无效的问题及解决

    这篇文章主要介绍了mysql修改自增主键数值无效的问题及解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • MySQL运维实战之使用二进制安装部署

    MySQL运维实战之使用二进制安装部署

    这篇文章主要为大家介绍了MySQL运维实战之使用二进制安装部署示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 随机生成八位优惠码并保存至Mysql数据库

    随机生成八位优惠码并保存至Mysql数据库

    这篇文章主要介绍了随机生成八位优惠码并保存至Mysql数据库的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-02-02
  • MySQL与PHP的基础与应用专题之自连接

    MySQL与PHP的基础与应用专题之自连接

    MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,本系列将带你掌握php与mysql的基础应用,本篇从自连接开始
    2022-02-02
  • Linux下安装mysql-8.0.20的教程详解

    Linux下安装mysql-8.0.20的教程详解

    这篇文章主要介绍了Linux下安装mysql8.0.20的教程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • MySQL字符串前缀索引使用

    MySQL字符串前缀索引使用

    本文主要介绍了MySQL字符串前缀索引使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • MySQL INNER JOIN 的底层实现原理分析

    MySQL INNER JOIN 的底层实现原理分析

    这篇文章主要介绍了MySQL INNER JOIN 的底层实现原理,INNER JOIN的工作分为筛选和连接两个步骤,连接时可以使用多种算法,通过本文,我们深入了解了MySQL中INNER JOIN的底层实现原理,需要的朋友可以参考下
    2023-06-06

最新评论