MySQL排序优化详细解析

 更新时间:2024年01月11日 09:22:07   作者:智由静生  
这篇文章主要介绍了MySQL排序优化详细解析,MySQL有两种方式生成有序的结果:1.通过排序操作;2.按索引顺序扫描,如果EXPLAIN出来的type列的值为"index",则说明使用了索引扫描来做排序,需要的朋友可以参考下

MySQL排序优化

MySQL有两种方式生成有序的结果:

1.通过排序操作;

2.按索引顺序扫描。如果EXPLAIN出来的type列的值为“index”,则说明使用了索引扫描来做排序。(但如果不为“index”,也不能说明没有使用索引扫描来做排序。)

一、使用索引生成排序

MySQL可以使用同一个索引既满足排序(ORDER BY),又用于查询(WHERE)操作的。因此如果可以,设计索引的时候尽可能考虑同时满足两种任务。

索引扫描本身是很快的,但如果索引不能覆盖查询所需的全部列,那就不得不每扫描一条索引记录就回表查询一次对应的行。这基本都是随机I/O,因此按索引顺序读取数据的速度通常要比顺序全表扫描慢。索引覆盖还有个额外的红利,就是主键。即使索引列中不包含主键,但因为二级索引的叶子节点包含了主键的值,所以也能用于对主键做覆盖查询。

只有当索引的列顺序和ORDER BY子句的顺序完全一致,并且所有列的排序方向都一样,MySQL才能使用索引对结果进行排序。如果查询关联多张表,则只有当ORDER BY子句引用的字段全部为第一张表时,才能使用索引做排序。

ORDER BY子句使用索引的限制和where查询是一样的,都需要满足左前缀要求。但有一种情况ORDER BY子句可以不满足左前缀要求。如果where子句或者join子句中对相关列指定了常量,就可以弥补索引的不足。

例如,有一张租赁表rental在列 (rental_data, inventory_id, customer_id) 上有索引。可以使用该索引为以下查询做排序。EXPLAIN中可以看到没有出现文件排序 (filesort)。

即使ORDER BY子句不满足索引的最左前缀的要求,也可以用于查询排序,这是因为索引的第一列被指定为一个常数。这个查询在不同版本的MySQL中可能会有不同的表现。因为select列中的staff_id不在排序索引中,而且不是主键,没有实现索引覆盖,因此按索引顺序读取数据的速度通常要比顺序全表扫描慢,有些版本的MySQL可能会通过计算成本选择文件排序 (filesort)。如果只有rental_id列就没问题了,前面说过主键有额外的“红利”。

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

--排序方向与索引列不一致
WHERE rental_date='1999-05-05'
ORDER BY inventory_id DESC,customer_id ASC
--排序字段包含一个不在索引中的字段
WHERE rental_date='1999-05-05'
ORDER BY inventory_id ,staff_id
--排序不满足最左法则
WHERE rental_date='1999-05-05'
ORDER BY customer_id 
--rental_date使用了范围查询,后续索引列失效
WHERE rental_date>'1999-05-05'
ORDER BY inventory_id,customer_id 
#inventory_id 使用了in多个等值条件查询,in对于排序认为是一种范围查询
WHERE rental_date='1999-05-05' AND inventory_id in (xx,xx)
ORDER BY customer_id 

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

应该尽可能使用更多的索引列。索引只能使用索引的最左前缀,当遇到第一个范围查询,就会停止使用后面的索引列。MYSQL无法再使用范围列后面的其他字段进行排序了,但对于“多个等值条件查询”则没有限制,所以可以考虑把范围查询语句改写成IN列表的形式。但是IN在where条件中不算范围查询,但对于order by不适用,对于排序认为是一种范围查询。在前面举的不能使用索引做排序的例子的最后一个就说明了这个问题。

如果排序查询中有LIMIT,那么LIMIT也会在排序之后应用,所以即使需要返回较少的数据,需要排序的数据量仍然非常大(虽然MySQL后续版本做了优化,根据实际情况抛弃不满足条件的结果,然后再排序)。所以此时如果能使用索引排序是最好的选择。

如果服务器能够按需要顺序读取数据,那么就不再需要额外的排序操作,并且group by查询也无需再做排序和将行按组进行聚合计算了。

二、文件排序

当不能使用索引生成排序结果时,需要进行文件排序(filesort),如果数据量小则在内存中进行,如果数据量大则需要使用磁盘,这两种情况都叫文件排序(filesort)。如果需要排序的数据量小于“排序缓冲区”,就使用内存“快速排序”。如果内存不够,就先将数据分块,对每个独立的块使用“快速排序”,并将各个块的排序结果存放正在磁盘上,然后将各个块进行合并(mergge),最后返回排序结果。

在关联查询的时候如果需要排序,MySQL会分两种情况处理这样的文件排序。如果ORDER BY子句的所有列都来自关联的第一张表,那么MySQL在关联处理第一个表的时候就进行文件排序。如果是这样,那么在MySQL的EXPLAIN结果中可以看到Extra字段会有“Using filesort”。除此以外的所有情况,MySQL都会先将关联的结果存放到一个临时表中,然后在所有关联都结束后,再进行文件排序。这种情况下,在MySQL的EXPLAIN结果中的Extra字段可以看到“Using temporary; Using filesort”。

所以尽量使ORDER BY子句的所有列都来自关联的第一张表。

到此这篇关于MySQL排序优化详细解析的文章就介绍到这了,更多相关MySQL排序优化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Xampp中mysql无法启动问题的解决方法

    Xampp中mysql无法启动问题的解决方法

    最近有朋友反映遇到了xampp的mysql启动不了这种情况,该怎么办呢,所以下面这篇文章主要给大家介绍了关于Xampp中mysql无法启动问题的解决方法,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • MySQL对小数进行四舍五入的操作实现

    MySQL对小数进行四舍五入的操作实现

    数学函数是MySQL中常用的一类函数,其主要用于处理数字,包括整型和浮点数等等,本文主要介绍了MySQL对小数进行四舍五入的操作实现,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • MySQL数据库数据删除操作详解

    MySQL数据库数据删除操作详解

    本文我们将要学习的是作为删除数据使用的 “DELETE” 语句,“DELETE” 语句是用来删除数据的,它不能用来删除数据表本身。删除数据表使用的是 “DROP” 语句,而 “DELETE” 的作用只是用来删除记录而已
    2022-08-08
  • MySQL 中定位 DDL 被阻塞的问题及解决方案

    MySQL 中定位 DDL 被阻塞的问题及解决方案

    DDL 被阻塞了,如何找到阻塞它的 SQL?下面,就这个问题,给一个清晰明了、拿来即用的解决方案,本文通过一个简单的demo给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2022-01-01
  • MySQL事务的ACID特性以及并发问题方案

    MySQL事务的ACID特性以及并发问题方案

    这篇文章主要介绍了MySQL事务的ACID特性以及并发问题方案,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-07-07
  • MySQL5.7的sql脚本导入到MySQL5.5出错3种解决方案

    MySQL5.7的sql脚本导入到MySQL5.5出错3种解决方案

    笔者需要将使用MySQL5.7数据库的网站挪入winows服务器,目标服务器使用的是MySQL5.5,因为兼顾到以前的网站,MySQL不能升级。遇到MySQL5.7的sql脚本导入到MySQL5.5出错,总结了3种解决方案,总有一个方案适合你。
    2023-06-06
  • MySQL中使用流式查询避免数据OOM

    MySQL中使用流式查询避免数据OOM

    这篇文章主要介绍了MySQL中使用流式查询避免数据OOM,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • MySQL如何利用DCL管理用户和控制权限

    MySQL如何利用DCL管理用户和控制权限

    这篇文章主要介绍了MySQL如何利用DCL管理用户和控制权限,帮助大家更好的理解和学习MySQL的使用,感兴趣的朋友可以了解下
    2020-11-11
  • MySQL异常处理浅析

    MySQL异常处理浅析

    这篇文章主要介绍了MySQL的异常处理,需要的朋友可以参考下
    2014-06-06
  • mysql 5.7.23 安装配置方法图文教程

    mysql 5.7.23 安装配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 5.7.23安装配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09

最新评论