Mysql优化(三):优化order by

MySQL中的两种排序方式

  1. .通过有序索引顺序扫描直接返回有序数据
    因为索引的结构是B+树,索引中的数据是按照一定顺序进行排列的,所以在排序查询中如果能利用索引,就能避免额外的排序操作。EXPLAIN分析查询时,Extra显示为Using index。MySQL会结合SQL中的where、order by中的字段去选择索引。
  2. .Filesort排序即对返回的数据进行排序
    所有不是通过索引直接返回排序结果的操作都是Filesort排序,也就是说进行了额外的排序操作。EXPLAIN分析查询时,Extra显示为Using filesort。

无法使用索引排序的情况

首先要注意:

MySQL一次查询只能使用一个索引,如果要对多个字段使用索引,建立复合索引。

注:下列key指代索引,key_part1、key_part2…指代索引中的顺序字段

  1. 排序字段在不同的索引中,无法使用索引排序:
SELECT * FROM t1 ORDER BY key1_part1, key2_part1;
  1. 对关键字的非连续元素使用ORDER BY,order by 使用索引除了前导列为常量时可以不满足最左前缀原则,其他时候都需要满足最左前缀原则
//跳过了key_part1,不满足最左前缀不使用索引
SELECT * FROM t1 ORDER BY key_part2;//前导列为常量,此时可以不满足最左前缀,使用索引
SELECT * FROM t1 WHERE key_part1=常量 ORDER BY key_part2;
  1. 混合ASC和DESC:
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC
  1. 用于查询行的索引与ORDER BY中所使用的索引不相同
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
  1. 有不同的ORDER BY和GROUP BY表达式。
SELECT * FROM t1 WHERE key_part1=constant ORDER BY key_part2 group by key_part3;

通过B+Tree结构判断索引是否能用于排序

索引是B+Tree的结构,能否使用某个索引来避免排序可以通过数据在B+Tree中的是否有序判断,下文有具体例子。

InnoDB的聚簇索引结构如下:
在这里插入图片描述

由此可知道,聚簇索引可以用于主键的排序,即order by 主键。

InnoDB的二级索引结构如下:
在这里插入图片描述
(1)二级索引的叶节点并不包含行记录的全部数据,仅包含索引中的所有键和一个用于查找对应行记录的主键值。(非叶子节点不包含主键

(2)Innodb二级索引,索引列值全相同的情况下,节点按主键值排序。

(3)二级索引键值的顺序和聚簇索引键值顺序通常不同,所以二级索引做范围查询读取记录的性能通常不如聚簇索引高效查询的列不存在二级索引时需要回表,回表操作会有大量的随机IO)。

是否使用索引排序取决于使用索引的成本

在满足了使用索引排序的条件(上文提及不可用索引排序的情况)的前提下,是否使用索引、使用哪个索引取决于使用索引的成本

设有表 t(id, create_at),主键为id,同时有索引 index(create_at)。不同查询索引 index(create_at) 的使用情况:
(1)SELECT id FROM t WHERE create_at='2019年10月15日' ORDER BY idSELECT create_at FROM t WHERE create_at='2019年10月15日' ORDER BY id
在这里插入图片描述
等值查询,create_at='2019年10月15日'的节点在 索引 index(create_at)结构中按主键(id)的顺序存储,因此使用index(create_at)可以避免排序,同时因为覆盖了所有列,无需回表(Extra 出现 Using index)

(2)SELECT * FROM t WHERE create_at='2019年10月15日' ORDER BY id
在这里插入图片描述
等值查询,create_at='2019年10月15日'的节点在 索引 index(create_at)结构中按主键(id)的顺序存储,因此使用index(create_at)可以避免排序,虽然需要回表但是通过索引可以过滤大部分的数据,成本低于使用聚簇索引

(3)SELECT * FROM t WHERE create_at>'2019年10月15日' ORDER BY id
在这里插入图片描述
索引 index(create_at) 不包含所有数据,因此使用 index(create_at)做范围查询,每读取每条记录都需要回表查询,会有大量的随机IO,同时,此时在index(create_at)上id是无序的,所以性能不如直接使用聚簇索引。所以该查询使用主键,通过对主键的聚簇索引进行扫描,只需要过滤掉不满足条件的值而不需要排序

范围查询,需要回表,回表操作会有大量的随机IO
(4)SELECT create_at FROM t WHERE create_at>'2019年10月15日' ORDER BY id
SELECT id FROM t WHERE create_at>'2019年10月15日' ORDER BY id
在这里插入图片描述
此查询因为索引 index(create_at) 包含所需列,不需要回表查询,因此使用index(create_at) 可以扫描更少的行,成本低于使用主键索引。

参考

  • 推荐阅读:浅谈InnoDB中的聚簇索引和二级索引[译]
  • order by 原理以及优化
  • MySQL——优化ORDER BY语句
  • MySQL官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/330103.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

漫画:什么是服务熔断

转载自 漫画:什么是服务熔断什么是服务熔断?熔断这一概念来源于电子工程中的断路器(Circuit Breaker)。在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性&#…

rabbitmq手动确认ack

【README】 参考 https://blog.csdn.net/u012943767/article/details/79300673 ; 【0】声明交换机,队列 与绑定 /*** 交换机,队列声明与绑定 */ public class AckDeclarer {/** 确认交换机 */public static final String ACK_EXCHANGE2 &q…

python图片保存_python读取和保存图片5种方法对比

python读取和保存图片5种方法对比 python中对象之间的赋值是按引用传递的,如果需要拷贝对象,需要用到标准库中的copy模块 方法一:利用 PIL 中的 Image 函数 这个函数读取出来不是 array 格式,这时候需要用 np.asarray(im) 或者 np…

finally块不被执行的情况总结

finally块的作用 通常用于处理善后工作。当try块里出现异常时,会立即跳出try块,到catch块匹配对应的异常,执行catch块里的语句。此时,可能在try块里存在打开的文件没关闭,连接的网络没断开,这部分资源是GC…

rabbitmq生产者基于事务实现发送确认

【README】 业务场景: 业务处理伴随消息的发送,业务处理失败(事务回滚)后要求消息不发送。 补充1:ACK与CONFIRM的区别 ACK-消费者消费成功后确认;(消费者确认已收到) CONFIRM-事…

什么是CAP定理

转载自 什么是CAP定理计算机界有很多高大上又难于理解的术语,CAP就是其中之一, 什么一致性(Consistency), 可用性(Availability), 分区容错性(Partition tolerance&#…

python找不到指定的文件夹里_Python环球网在Unix中的指定文件路径中找不到*.txt

我在Windows环境中写了一些文件,我在转换文件时遇到了麻烦。在Windows中,我通常使用类似以下内容读取目录中的所有.txt文件:pathtotxt "C:\\Text Data\\EJC\\Philosophical Transactions 1665-1678\\*\\*.txt" for file in glob.g…

从开发者角度谈Mysql主键

转载自 从开发者角度谈Mysql主键说在前面零度mysql一直比较薄弱,俗话说的好,不会mysql的程序员不是好程序员,刚刚好认识mysql大牛刘龘刘,刚刚好就有了这些文章,主要是刘龘刘大牛写的,零度稍微修改成文&…

JVM内存结构分析:为什么需要S0和S1?

一、为什么会有年轻代 我们先来屡屡,为什么需要把堆分代?不分代不能完成他所做的事情么?其实不分代完全可以,分代的唯一理由就是优化GC性能。你先想想,如果没有分代,那我们所有的对象都在一块,…

rabbitmq-消息追踪rabbitmq_tracing

【README】 消息中心的消息追踪需要使用 Trace 实现,Trace是 rabbitmq用于记录每一次发送的消息;方便开发者调试,排错。可通过插件形式提供可视化界面。 【1】 开启消息追踪 1)消息追踪通过 rabbitmq的插件 trace 来实现&#x…

python大神交流网站_学习Python必去的8个网站

作为一个现时代的程序员初学者,除了看书之外,互联网的学习手段也是断不能少的! 以下这些网站,虽说不上全方位的满足你的需求,但是大部分也都能! 0.国外的大神GitHub : https://github.com/pypa/…

一文理清Http2.0

前言 HTTP2.0主要有三大特性:二进制协议、头部压缩、服务端推送(Server Push)、多路复用。本文从分析http1.x存在的问题入手,逐一介绍http2.0的优势。 Http1.x存在的问题 在HTTP1.0下,HTTP1.1非Keep-Alive模式下&am…

收敛和发散思维如何被用作解决问题的手段

转自: https://www.jdon.com/mda/thinking.html 将发散和收敛的思想结合在一起使用时,可以帮助分析人员得出更好的和更有创造性的解决方案。发散性思维是将一个话题分解并产生许多从原始概念中分支出来的想法的过程,而收敛性思维则是集中于少…

关于python面向对象编程中、下列说法中_关于Python面向对象编程的知识点总结

前言 如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些面向对象语言的一些基本特征,在头脑里头形成一个基本的面向对象的概念,这样有助于你更容易的学习Python的面向对象编程。 接下来我们就来了解关于Python面向对象编程的知…

Java开发必会的反编译知识

转载自 Java开发必会的反编译知识 编程语言在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language)。编程语言(Programming Language)分为低级语言(Low-level Language)和高…

happen-before原则的理解

前言 在程序执行时,为了提高性能,编译器和处理器会对指令进行重排序。 为了明确定义多线程场景下重排序的问题(可见性、有序性、原子性),Java引入了JMM(Java Memory Model),也就是Java内存模型。JMM为JAV…

转:RabbitMQ 消息队列特性知多少

转自: https://www.jianshu.com/p/94d6d5d98c3d 序言 现在我们每天都要与信息打交道,主动或被动的在创造或接收消息。你会收到话费通知短信,使用微信 QQ跟远在万里的朋友交流,也可能使用钉钉跟同事讨论工作,使用抖音…

easyui根据select下拉框内容更新表单内容_Ant Design 4.0 的一些杂事儿 - Select 篇

前几篇:Ant Design 4.0 的一些杂事儿 - Table 篇Ant Design 4.0 的一些杂事儿 - Form 篇聊完了 Table 和 Form 两个重型组件,我们来继续聊聊看起来不那么重的 Select 组件。它在 Ant Design 4.0 中有哪些变化。如果你读过 《Ant Design 4.0 进行时》&…

避免代码冗余,使用接口和泛型重构Java代码

转载自 避免代码冗余,使用接口和泛型重构Java代码在使用动态语言和.NET工作了若干年后,我又回到老本行–Java开发。在Ruby中,清除代码冗余是非常方便的,而在Java中则需要结合接口和泛型实现类似的功能。 原始代码 以下是这个类中的…

一文理类加载相关知识:类加载器、双亲委派、SPI

思维导图 类加载的时机 类加载的流程 类从被加载到内存中开始,直到被从内存中卸载为止,它的整个生命周期包括:验证、准备、解析、初始化、使用和卸载7 个阶段。 其中验证、准备、解析 3 个部分统称为连接(Linking) …