在开发过程中,遇到了一条 order by index limit 的语句,执行时间慢,下面记录一下分析过程和原因

问题 SQL

select * from t1 where call_type = 2 and sys_type = 1 order by third_id desc limit 1;

说明:数据库为 MySQL,引擎为 Innodb,版本为 5.6,其中third_id为普通索引。

对于一个慢 SQL,想到的第一部是通过 explain 查看其执行计划,上面这条 SQL 的执行计划如下:

id

select_type

table

type

possible_keys

key

key_len

ref

rows

Extra1

SIMPLE

call_record_log

index

idx_third_id

4

1

Using where

可以看到,启用了索引 id_third_id,下面就需要搞明白为什么 SQL 在启用了索引的情况下,还是很慢,有下面3个猜测:

因为在 SQL 中使用了 desc,猜测索引在被倒序排序的过程中耗时较长。

在我们使用 limit 的情况下引发了慢查询

order by index 的原因,根据 explain 的解释信息可以,type 类型为 index,而 index 类型通常来说是比较慢的一种情况。

下面我们针对这两种情况进行验证。

猜测1:索引倒序排序的问题

1、通过查询资料得到,在 MySQL 中,使用 Innodb 引擎的时候,索引的排序时有序的,通过正序使用和倒序使用不应该影响 MySQL 的查询效率()。

2、通过将 desc 改为 asc,在实际测试过程中发现,对返回数据影响最大的是第一条符合条件的记录出现的位置,即在找到第一条记录前,需要扫描多少条语句。

根据上面两点,可知:order by index desc/asc 并不是引发这条 SQL 产生慢查询的原因。

猜测2:limit 引发了慢查询

针对 limit 的使用情况,查询了 MySQL 使用手册,证实了猜测。摘录关键信息如下:

If you select only a few rows with LIMIT, MySQL uses indexes in some cases when normally it would prefer to do a full table scan.

大意:如果只是查询几条数据,MySQL 在某些情况下会使用索引,通常情况下回权标扫描。

这一点和我们上面看到的 explain 是一致的,使用了索引。但是并没有告诉我们会什么在使用了索引的情况下会慢,继而引发了猜测,是不是 limit 也是导致这个问题的原因呢。将 limit 条件去掉看一下 explain 的信息:

id

select_type

table

type

possible_keys

key

key_len

ref

rows

Extra1

SIMPLE

call_record_log

ALL

2133780

Using where; Using filesort

发现,此时执行的是全表扫描,并没有继续使用索引。可以得出的推断:

没有 limit 的情况下,没有像希望的那样使用索引,说明 MySQL 认为使用索引代价更大。

在有 limit 的情况下,会相当于强制使用了索引。

继续阅读手册中 order by 相关的东西,发现如下:

If you combine LIMIT row_count with ORDER BY, MySQL stops sorting as soon as it has found the first row_count rows of the sorted result, rather than sorting the entire result. If ordering is done by using an index, this is very fast. If a filesort must be done, all rows that match the query without the LIMIT clause are selected, and most or all of them are sorted, before the first row_count are found. After the initial rows have been found, MySQL does not sort any remainder of the result set.

大意:如果 order by 和 limit 组合使用,MySQL 在查询到对应的数据之后就会立即停止而不是排序全部的结果。如果 order by 使用了索引那么通常来说这个过程是很快的。如果 filesort 的操作必须被执行,在匹配到程序要查询的结果之前,这个 SQL 在没有 limit 的情况下查出来的绝大部分或者全部结果都会被排序。在最原始的记录被找到之后,MySQL 不再排序后面的任何结果集。

手册说在 order by 后面有索引的情况会 very fast,但是和我们的结果完全不同,没有在文档中找到解释慢查询的原因,先去看看 手册中关于 order by 的说明。

猜测3:order by index 引发了慢查询

查看对应的文档

In some cases, MySQL may use an index to satisfy an ORDER BY clause and avoid the extra sorting involved in performing a filesort operation.

The index may also be used even if the ORDER BY does not match the index exactly, as long as all unused portions of the index and all extra ORDER BY columns are constants in the WHERE clause. If the index does not contain all columns accessed by the query, the index is used only if index access is cheaper than other access methods.

大意:

在某些情况下,MySQL可能会使用索引来满足ORDER BY子句,并避免执行filesort操作时涉及的额外排序。

即使ORDER BY与索引不完全匹配,也可以使用索引,只要索引的所有未使用部分和所有额外的ORDER BY列都是WHERE子句中的常量即可。 如果索引不包含查询访问的所有列,则仅在索引访问比其他访问方法更便宜时才使用索引。

通过上面的描述,我们看到了解决问题的希望,即并不是在 order by 后面指定了索引索引就会被启用,只有当使用索引更为合适的情况下才会被使用,这和我们上面的 SQL 在没有 limit 的情况下执行的是全表扫面是一致的,即此种情况下 MySQL 执行全表扫描都比按照索引执行的顺序更高效。继续看文档。

SELECT * FROM t1ORDER BY key_part1, key_part2;

However, the query uses SELECT *, which may select more columns than key_part1 and key_part2. In that case, scanning an entire index and looking up table rows to find columns not in the index may be more expensive than scanning the table and sorting the results. If so, the optimizer probably will not use the index. If SELECT * selects only the index columns, the index will be used and sorting avoided.

大意:

但是,查询使用SELECT ,它可以选择比key_part1和key_part2更多的列。 在这种情况下,扫描整个索引并查找表行以查找不在索引中的列可能比扫描表并对结果进行排序更昂贵。 如果是这样,优化器可能不会使用索引。 如果SELECT仅选择索引列,则将使用索引并避免排序。

我们发现如果 order by 的索引没有覆盖掉全部的查询字段的时候,优化器认为使用索引是一种更昂贵的操作,就不在使用索引。终于在文档中发现了能够解释我们上面的 SQL 是查询耗时较长的原因了。

后续的文档给出了哪几种情况下 order by 的索引会生效,哪几种情况下是无效的,在此就不一一列举了。

到底如何优化上面的 SQL 呢

我们私下讨论的存在三个方向:

将 where 条件中涉及到的几个字段和 thrid 字段建立联合索引,同时select 字段要覆盖索引

将 order by third 替换成 primary key,可以在一定程度上解决这个问题。

根据具体的业务逻辑,重构 SQL。

本作品采用《CC 协议》,转载必须注明作者和本文链接

日拱一卒,功不唐捐

MySQL倒序查询最后三条语句_MySQL 中 一条 order by index limit 语句的分析相关推荐

  1. mysql 导入数据库sql语句_mysql中导入数据与导出数据库sql语句

    本文章来详细介绍关于mysql中导入数据与导出数据库sql语句,在mysql中常用的导入与导出数据的命令有source与mysqldump大家可参考. 1.例1:连接到本机上的MYSQL 首先在打开D ...

  2. set trans 必须是事务处理的第一个语句_MySQL中特别实用的几种SQL语句送给大家

    在写SQL时,经常灵活运用一些SQL语句编写的技巧,可以大大简化程序逻辑.减少程序与数据库的交互次数,有利于数据库高可用性,同时也能显得你的SQL很牛B,让同事们眼前一亮. 实用的SQL 1.插入或替 ...

  3. mysql中删除标识列的语句_MySQL中一些常用的数据表操作语句笔记

    0.创建表 CREATE TABLE 表名 (属性名 数据类型 [完整性约束条件], 属性名 数据类型 [完整性约束条件], 属性名 数据类型 [完整性约束条件]) "完整性约束条件&quo ...

  4. mysql去重查询的三种方法

    文章目录 前言 一.插入测试数据 二.剔除重复数据方法 1.方法一:使用distinct 2.方法二:使用group by 3.方法三:使用开窗函数 总结 前言 数据库生成环境中经常会遇到表中有重复的 ...

  5. mysql怎么保证最少一条消息_MySQL 的一条语句是怎么执行的

    该文为< MySQL 实战 45 讲>的学习笔记,感谢查看,如有错误,欢迎指正 一.MySQL 的基础架构 以下就是 MySQL 的基础架构图. 在 Linux 中安装 MySQL 时,最 ...

  6. mysql查询和修改一个命令_MYSQL的常用命令和增删改查语句

    连接命令:mysql -h[主机地址] -u[用户名] -p[用户密码] 创建数据库:create database [库名] 显示所有数据库: show databases; 打开数据库:use [ ...

  7. mysql join 排序_MySQL查询优化:连接查询排序limit(join、order by、limit语句)

    本文链接:https://blog.csdn.net/xiao__gui/article/details/8616224 不知道有没有人碰到过这样恶心的问题:两张表连接查询并limit,SQL效率很高 ...

  8. mysql 怎么查询慢sql语句_Mysql中 查询慢的 Sql语句的记录查找

    Mysql中 查询慢的 Sql语句的记录查找 慢查询日志 slow_query_log,是用来记录查询比较慢的sql语句,通过查询日志来查找哪条sql语句比较慢,这样可以对比较慢的sql可以进行优化. ...

  9. mysql导入多条数据语句_MySQL插入多条记录和REPLACE语句

    今天遇到样一个问题,在使用Mysql数据库时,新建一个表,并设置主键为自增长,结果当我一次执行多条插入语句时悲剧了,它竟然报错了,信息如下: 错误码: 1064 You have an error i ...

最新文章

  1. 面试AI算法岗,你被要求复现顶会了嘛?
  2. 鸿洋android屏幕适配四部曲-传送门
  3. spark 决策树分类算法demo
  4. Cocoon的sitemap详解
  5. kaggle竞赛--房价预测详细解读
  6. 从windows server的文件服务到分布式文件服务(十)
  7. Linux的Nginx一:概况
  8. Hibernate中对增删改查的小结
  9. 键盘跟计算机无法识别,键盘无法识别的原因与解决办法
  10. linux删除0字节的文件,如何在linux中删除许多0字节的文件?
  11. Vivado 错误代码 [DRC PDCN-2721] 解决
  12. Linux基础命令与操作
  13. 第13章WEB13-JSP模式JDBC高级篇
  14. 21年GitHub上最牛批的《Java工程师成神之路》最新版文档!限时开源
  15. 呼叫中心坐席功能在职场中的应用
  16. 电子元器件自动化测试系统|大功率分立器件测试系统NSAT-2000
  17. 数理统计基本概念梳理
  18. 【劳动最光荣】TcaplusDB祝大家劳动节快乐
  19. 混合牛奶 Mixing Milk
  20. javaweb第一季笔记【siki学院】

热门文章

  1. 帆软报表决策系统跨域登录
  2. 基于单片机的数字秒表
  3. 21考研:你是为了什么考研?
  4. 极限和连续+偏导+方向导数+可微+梯度+链式法则+hessian矩阵
  5. python爬虫(五)---斗鱼主播图片下载并重命名
  6. ps保存psd后图层全没了_明明只有几个图层,为什么我的 PSD 文件这么大?
  7. L1-059 敲笨钟
  8. PLC通讯实现-C#实现西门子PLC以太网通讯Sharp7(六)
  9. 2021域名过期会引发哪些问题?说说常见弊端
  10. 网站域名过期后还能买回来吗?