MySQL范围查询优化的场景实例详解
作者:lfwh 发布时间:2024-01-17 01:11:12
思考题
假设有一张订单表 order,主要包含了主键订单编码 order_no、订单状态 status、提交时间 create_time 等列,并且创建了 status 列索引和 create_time 列索引。此时通过创建时间降序获取状态为 1 的订单编码,以下是具体实现代码:
select order_no from order where status =1 order by create_time desc;
你知道其中的问题所在吗?我们又该如何优化?
解析
status和create_time单独建索引,在查询时只会遍历status索引对数据进行过滤,不会用到create_time列索引,将符合条件的数据返回到server层,在server对数据通过快排算法进行排序,Extra列会出现file sort;
应该利用索引的有序性,在status和create_time列建立联合索引,这样根据status过滤后的数据就是按照create_time排好序的,避免在server层排序
对的,为了避免文件排序的发生。因为查询时我们只能用到status索引,如果要对create_time进行排序,则需要使用文件排序filesort。
filesort是通过相应的排序算法将取得的数据在内存中进行排序,如果内存不够则会使用磁盘文件作为辅助。虽然在一些场景中,filesort并不是特别消耗性能,但是我们可以避免filesort就尽量避免。
阿里巴巴MySQL规范
【推荐】 如果有 order by 的场景,请注意利用索引的有序性。 order by 最后的字段是组合索引的一部分,并且放在索引组合顺序的最后,避免出现 file_sort 的情况,影响查询性能。
正例: where a=? and b=? order by c; 索引: a_b_c
反例: 索引如果存在范围查询, 那么索引有序性无法利用,如: WHERE a>10 ORDER BY b; 索引 a_b 无 法排序
范围查询-基础
讲联合索引,一定要扯最左匹配!
最左匹配 所谓最左原则指的就是如果你的 SQL 语句中用到了联合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个联合索引去进行匹配,值得注意的是,当遇到范围查询(>、<、between、like)就会停止匹配。 假设,我们对(a,b)字段建立一个索引,也就是说,你where后条件为
a = 1
a = 1 and b = 2
是可以匹配索引的。但是要注意的是~你执行
b= 2 and a =1
也是能匹配到索引的,因为Mysql有优化器会自动调整a,b的顺序与索引顺序一致。 相反的,你执行
b = 2
就匹配不到索引了。 而你对(a,b,c,d)建立索引,where后条件为
a = 1 and b = 2 and c > 3 and d = 4
那么,a,b,c三个字段能用到索引,而d就匹配不到。因为遇到了范围查询!
场景一: a = 1 and b = 2 and c = 3
如果sql为
SELECT * FROM table WHERE a = 1 and b = 2 and c = 3;
如何建立索引?
如果此题回答为对(a,b,c)建立索引,那都可以回去等通知了。
此题正确答法是,(a,b,c)或者(c,b,a)或者(b,a,c)都可以,重点要的是将区分度高的字段放在前面,区分度低的字段放后面。像性别、状态这种字段区分度就很低,我们一般放后面。
例如假设区分度由大到小为b,a,c。那么我们就对(b,a,c)建立索引。在执行sql的时候,优化器会 帮我们调整where后a,b,c的顺序,让我们用上索引。
阿里巴巴Java 开发手册
【强制】 在 varchar 字段上建立索引时,必须指定索引长度,没必要对全字段建立索引,根据 实际文本区分度决定索引长度。
说明: 索引的长度与区分度是一对矛盾体,一般对字符串类型数据,长度为 20 的索引,区分度会高达 90%以上,可以使用 count(distinct left(列名, 索引长度))/count(*)的区分度来确定。
场景二: a > 1 and b = 2
如果sql为
SELECT * FROM table WHERE a > 1 and b = 2;
如何建立索引?
如果此题回答为对(a,b)建立索引,那都可以回去等通知了。
此题正确答法是,对(b,a)建立索引。如果你建立的是(a,b)索引,那么只有a字段能用得上索引,毕竟最左匹配原则遇到范围查询就停止匹配。
如果对(b,a)建立索引那么两个字段都能用上,优化器会帮我们调整where后a,b的顺序,让我们用上索引。
场景三:a > 1 and b = 2 and c > 3
如果sql为
SELECT * FROM `table` WHERE a > 1 and b = 2 and c > 3;
如何建立索引? 此题回答也是不一定,(b,a)或者(b,c)都可以,要结合具体情况具体分析。
拓展一下
SELECT * FROM `table` WHERE a = 1 and b = 2 and c > 3;
怎么建索引?嗯,大家一定都懂了!
场景四: a > 1 ORDER BY b
SELECT * FROM `table` WHERE a = 1 ORDER BY b;
如何建立索引? 这还需要想?一看就是对(a,b)建索引,当a = 1的时候,b相对有序,可以避免再次排序! 那么
SELECT * FROM `table` WHERE a > 1 ORDER BY b;
如何建立索引?
对(a)建立索引,因为a的值是一个范围,这个范围内b值是无序的,没有必要对(a,b)建立索引。
拓展一下
SELECT * FROM `table` WHERE a = 1 AND b = 2 AND c > 3 ORDER BY c;
怎么建索引?
场景五: a IN (1,2,3) and b > 1
SELECT * FROM `table` WHERE a IN (1,2,3) and b > 1;
如何建立索引?
还是对(a,b)建立索引,因为IN在这里可以视为等值引用,不会中止索引匹配,所以还是(a,b)!
拓展一下
SELECT * FROM `table` WHERE a = 1 AND b IN (1,2,3) AND c > 3 ORDER BY c;
如何建立索引?此时c排序是用不到索引的。
来源:https://blog.csdn.net/weixin_42326851/article/details/124993822


猜你喜欢
- 摘要:本篇博客将详细介绍如何对YOLOv5车牌识别模型进行优化和部署。我们将讨论模型优化策略,如模型蒸馏、模型剪枝和量化等。此外,我们还将介
- 相信大家从去年圣诞节开始,逐渐发现淘宝网首页的标志开始有了新的形式,从过往的静态图片节日LOGO变成了FLASH的动画小故事LO
- Python try重新执行:def numberinput(): #创建方法 try: s=int(input('n
- 运行方法: 1. 打开python2 IDLE; 2. 输入 fro
- argparse 是python自带的命令行参数解析包,可以用来方便地读取命令行参数。一、传入一个参数import argpars
- 何时使用单体 RESTful 服务对于很多初创公司来说,业务的早期我们更应该关注于业务价值的交付,而单体服务具有架构简单,部署简单,开发成本
- 研究了几天Adodb.stream和XMLHTTP的应用,找了不少很有趣的教程,下面的代码是将一个远程的页面,图片地址保存到本地的实例。将代
- 本文实例讲述了python对象转字典的两种实现方式。分享给大家供大家参考,具体如下:一. 方便但不完美的__dict__对象转字典用到的方法
- 常用 ASCII 码表对照表:注意如下几点:0-9:48-57A-Z:65-90a-z:97-122ord()函数介绍: ord(
- 基本类型转换python3与python2通用函数:int('123456',10) # 转换为指定进制的整数hex(123
- 昨时要导一些数据,从网上搜到的。字段多时insert 语句生成的不完整了,还没有找到原因..有个缺点……就是标识种子的列 也insert了c
- 假设我有一个DataFrame(df)如下:name age idmike 10 1tony 14 2lee 20 3现在我想把id 放到最
- laravel入门简介作为PHP最常用的框架之一,Laravel的框架目录布置得尤其清晰,适用于各种类型的项目开发。今天来记录下larave
- 可以,具体方法如下::<% set fs=createobject("scripting.
- python清空命令行 !有时我们在命令行上运行一些代码时,觉得有些冗余了,可以通过以下代码进行清除命令行上的代码。import osdef
- 一、线程池简介传统多线程方案会使用“即时创建,即时销毁”的策略。尽管与创建进程相比,创建线程的时间已
- 1、用apt-get安装mysql#更新一下apt 仓库sudo apt-get update#安装mysql-servicesudo ap
- 在用HTML(HyperText Markup Language,超文本链接标示语言)语言编写Web页面时,由于所用的Web浏览器对HTML
- Apache SkyWalking 在本月初发布了 SkyWalking Backend、UI 的 9.2.0 版本 以及&nbs
- 一、ASP的平反想到ASP 很多人会说 “asp语言很蛋疼,不能面向对象,功能单一,很多东西实现不了” 等等诸如此类。 以上说法都是错误的,