Mysql索引扫描排序

2024-09-03 18:38

本文主要是介绍Mysql索引扫描排序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用索引扫描来做排序

生成有序结果

Mysql有两种操作可以用来生成有序结果:
+ 排序操作: 将查找出来的结果使用排序算法进行排序
+ 按索引顺序扫描ORDER BY语句后跟着一个被索引的列,如此一来索引的顺序就是索引对应记录的顺序,这样直接顺着索引一直往下读取记录即可得到有序的结果。

建立用于排序扫描的索引

按照索引顺序扫描的好处是不言而喻的,因为查找出来的结果就是有序结果而无需执行额外的排序操作,这样执行的速度就会相对较快。但是,不是什么时候按照索引扫描的执行速都会是最快的。虽然扫描索引的速度是非常快的,但是如果索引不能覆盖到查询所需要的所有数据列的话,这种情况下每扫描一个索引就必须相对应地回表一次,这样的IO几乎是随机IO,如此一来虽然索引扫描无需执行一次排序算法,但是随机IO操作会大大拖慢执行速度,导致按照索引扫描的执行速度反而要比排序操作要慢。因此,在考虑使用按照索引扫描的方式去获得有序结果,那么设计索引时必须要考虑索引覆盖的情况

什么时候Mysql会使用索引排序?

  • 索引列的顺序与 ORDER BY字句的顺序一致时,并且所有列的排列顺序一样。
    因为多列索引的索引值是综合了多个列计算而得的,且计算的结果与列的顺序有关。例如下面就是一个例子:

    //伪代码
    index_t hash(string x, string y, string z){return x.append(y).append(z);
    }

    当执行ORDER BY x, y, z时,实际上就是ORDER BY hash(x, y, z),这样必须保证x, y, z的顺序与建立索引时一致,索引顺序对应的记录顺序才与排序的顺序一致,这样才可以使用索引扫描进行排序。

  • 当查询关联多张表时,则只有当ORDER BY中引用的字段全为第一张表中的字段,才可能使用索引排序。
  • 有一种例外,ORDER BY后跟的字段可以不满足最左前缀原则:当前导量为常量的时候

几个例子

  1. 有一张表rental如下所示:
CREATE TABLE rental{...PRIMARY KEY(rental_id),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),...
};

执行语句:

EXPLAIN SELECT rental_id, staff_id FROM sakila.rental 
-> WHERE rental_date = '2005-05-5'
-> ORDER BY inventory_id, customer_id\G

输出为:

possible_keys: rental_datekey: rental_daterows: 1extra: using where

这里看到extra: using where而不是extra: using filesort表明此次查找并没有排序操作,而是直接通过扫描索引获得有序结果。因为这在这里,虽然ORDER BY语句的字段并没有满足最左前缀的原则,但是由于前导列只定了一个常量,所以可以使用索引扫描进行排序。

  1. 将上述查询改为以下语句也没问题:
EXPLAIN SELECT rental_id, staff_id FROM sakila.rental 
-> WHERE rental_date > '2005-05-5'
-> ORDER BY rental_date, inventory_id, customer_id\G

因为这里虽然没有将前导列指定为常量,但是这里ORDER BY的语句满足了最左前缀原则。

  1. 下列语句不能使用扫描索引得到有序结果:
    • ...WHERE rental_date > '2005-05-5' ORDER BY rental_date DESC, inventory_id ASC
      因为排序方向不一致。
    • ...WHERE rental_date = '2005-05-5' ORDER BY rental_date , staff_id
      因为使用了一个不在索引中的列。
    • ...WHERE rental_date > '2005-05-5' ORDER BY inventory_id
      因为不满足最左前缀索引

这篇关于Mysql索引扫描排序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1133726

相关文章

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Mysql表的简单操作(基本技能)

《Mysql表的简单操作(基本技能)》在数据库中,表的操作主要包括表的创建、查看、修改、删除等,了解如何操作这些表是数据库管理和开发的基本技能,本文给大家介绍Mysql表的简单操作,感兴趣的朋友一起看... 目录3.1 创建表 3.2 查看表结构3.3 修改表3.4 实践案例:修改表在数据库中,表的操作主要

mysql出现ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘localhost‘ (10061)的解决方法

《mysql出现ERROR2003(HY000):Can‘tconnecttoMySQLserveron‘localhost‘(10061)的解决方法》本文主要介绍了mysql出现... 目录前言:第一步:第二步:第三步:总结:前言:当你想通过命令窗口想打开mysql时候发现提http://www.cpp

MySQL大表数据的分区与分库分表的实现

《MySQL大表数据的分区与分库分表的实现》数据库的分区和分库分表是两种常用的技术方案,本文主要介绍了MySQL大表数据的分区与分库分表的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有... 目录1. mysql大表数据的分区1.1 什么是分区?1.2 分区的类型1.3 分区的优点1.4 分

MySQL错误代码2058和2059的解决办法

《MySQL错误代码2058和2059的解决办法》:本文主要介绍MySQL错误代码2058和2059的解决办法,2058和2059的错误码核心都是你用的客户端工具和mysql版本的密码插件不匹配,... 目录1. 前置理解2.报错现象3.解决办法(敲重点!!!)1. php前置理解2058和2059的错误

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

MySQL INSERT语句实现当记录不存在时插入的几种方法

《MySQLINSERT语句实现当记录不存在时插入的几种方法》MySQL的INSERT语句是用于向数据库表中插入新记录的关键命令,下面:本文主要介绍MySQLINSERT语句实现当记录不存在时... 目录使用 INSERT IGNORE使用 ON DUPLICATE KEY UPDATE使用 REPLACE

MySQL Workbench 安装教程(保姆级)

《MySQLWorkbench安装教程(保姆级)》MySQLWorkbench是一款强大的数据库设计和管理工具,本文主要介绍了MySQLWorkbench安装教程,文中通过图文介绍的非常详细,对大... 目录前言:详细步骤:一、检查安装的数据库版本二、在官网下载对应的mysql Workbench版本,要是

mysql数据库重置表主键id的实现

《mysql数据库重置表主键id的实现》在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,本文主要介绍了mysql数据库重置表主键id的实现,具有一定的参考价值,感兴趣的可以了... 目录关键语法演示案例在我们的开发过程中,难免在做测试的时候会生成一些杂乱无章的SQL主键数据,当我们

浅谈mysql的sql_mode可能会限制你的查询

《浅谈mysql的sql_mode可能会限制你的查询》本文主要介绍了浅谈mysql的sql_mode可能会限制你的查询,这个问题主要说明的是,我们写的sql查询语句违背了聚合函数groupby的规则... 目录场景:问题描述原因分析:解决方案:第一种:修改后,只有当前生效,若是mysql服务重启,就会失效;