✅什么是最左前缀匹配?为什么要遵守?

在 MySQL 中,最左前缀匹配指的是在查询时利用索引的最左边部分进行匹配。当你执行查询时,如果查询条件涉及到组合索引的前几个列,MySQL 就能够利用该复合索引来进行匹配。

组合索引即由多个字段组成的联合索引,比如 idx_col1_col2_col3 (col1,col2,col3)。

假设我们创建了一个组合索引 (col1, col2, col3),如果查询条件是针对 col1、(col1, col2) 或者 (col1, col2, col3),那么 MySQL 就能利用该复合索引进行最左前缀匹配。

然而,如果查询条件只涉及到 col2、只涉及到 col3 或者只涉及到 col2 和 col3,也就是没有包含 col1,那么通常情况下(不考虑索引跳跃扫描等其他优化),就无法利用该索引进行最左前缀匹配。

值得注意的是,最左前缀匹配与查询条件的顺序无关。无论你写的是 where col1 = “Paidaxing” and col2 = “666” 还是 where col2 = “666” and col1 = “Paidaxing”,对结果都没有影响,命中的结果仍然一样。

此外,需要大家注意的是,许多人可能会误以为创建一个组合索引 (col1, col2, col3) 时,数据库会创建三个索引 (col1)、(col1, col2) 和 (col1, col2, col3),这样的理解其实是不正确的。实际上,数据库只会创建一棵 B+树,只不过在这颗树中,首先按照 col1 进行排序,然后在 col1 相同时再按照 col2 排序,col2 相同再按照 col3 排序。

另外,如果没有涉及到联合索引,单个字段的索引也需要遵守最左前缀原则。即当一个字段的值为"abc"时,当我们使用 like 进行模糊匹配时,like "ab%" 是可以利用索引的,而 "%bc"则不行,因为后者不符合最左前缀匹配的原则。

为什么要遵循最左前缀匹配

我们都了解,在 MySQL 的 InnoDB 引擎中,索引是通过 B+树来实现的。不论是普通索引还是联合索引,都必须构建 B+树的索引结构。

针对普通索引,其存储结构是在 B+树的每个非叶子节点上记录索引的值,而在 B+树的叶子节点上,则记录了索引的值和聚簇索引(主键索引)的值。

如:
image.png

(这样图是简化的,实际上还有双向链表,具体的可以参考索引介绍的文章)

在联合索引中,比如联合索引 (age, name),同样也是构建了一棵 B+树。在这棵 B+树中,非叶子节点中记录的是 name 和 age 两个字段的值,而在叶子节点中记录的是 name、age 两个字段以及主键 id 的值。

image.png

在存储过程中,如上所述,当 age 不同时,按照 age 排序;当 age 相同时,则按照 name 排序。

因此,了解了索引的存储结构之后,我们就很容易理解最左前缀匹配了:由于索引底层是一棵 B+树,如果是联合索引的话,在构造 B+树时,会先按照左边的键进行排序,当左边的键相同时,再依次按照右边的键进行排序。

因此,在通过索引查询时,也需要遵守最左前缀匹配的原则,即需要从联合索引的最左边开始进行匹配。这就要求查询语句的 WHERE 条件中包含最左边的索引值。

MySQL 索引一定遵循最左前缀匹配吗?

因为索引底层是一个 B+树,如果是联合索引的话,在构造 B+树的过程中,会先按照左边的键进行排序。当左边的键相同时,再依次按照右边的键排序。

因此,在通过索引进行查询时,也需要遵守最左前缀匹配的原则,即需要从联合索引的最左边开始进行匹配。这就要求查询语句的 WHERE 条件中包含最左边的索引值。这就是最左前缀匹配的概念。

在 MySQL 之前的版本中,一直都是遵循最左前缀匹配的原则,这句话在以前是正确的,没有任何问题。但是在 MySQL 8.0 中,情况就有所不同了。因为在 8.0.13 中引入了索引跳跃扫描的特性。

补充知识

索引跳跃扫描

MySQL 8.0.13 版本引入了索引跳跃扫描(Index Skip Scan)优化,对于 range 查询提供了支持。即使不符合组合索引最左前缀原则的条件下,SQL 依然能够使用组合索引,从而减少不必要的扫描。

让我们通过一个例子来解释一下。首先,我们有下面这样一张表(参考了 MySQL 官网的例子,但经过了一些改动和优化):

CREATE TABLE t1 (f1 INT NOT NULL, f2 INT NOT NULL);
CREATE INDEX idx_t on t1(f1,f2);
INSERT INTO t1 VALUES(1,1), (1,2), (1,3), (1,4), (1,5),(2,1), (2,2), (2,3), (2,4), (2,5);
INSERT INTO t1 SELECT f1, f2 + 5 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 10 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 20 FROM t1;
INSERT INTO t1 SELECT f1, f2 + 40 FROM t1;

通过以下 SQL 语句,先创建一张名为 t1 的表,并将字段 f1 和 f2 设置为联合索引。然后向其中插入一些记录。

接着,分别在 MySQL 5.7.9 和 MySQL 8.0.30 上执行EXPLAIN SELECT f1, f2 FROM t1 WHERE f2 = 40;

image.png

可以看到,主要有以下几个区别:

MySQL 5.7 中,type = index,rows=160,extra=Using where;Using index

MySQL 8.0 中,type = range,rows=16,extra=Using where;Using index for skip scan

type 字段表示扫描方式,其中 range 表示范围扫描,而 index 表示索引树扫描。通常情况下,范围扫描要比索引树扫描快得多。

通过 rows 字段也能够观察到这一点,使用索引树扫描的方式共扫描了 160 行,而范围扫描方式只扫描了 16 行。

然后,关键在于为什么 MySQL 8.0 中的扫描方式更快呢?这主要是因为采用了"Using index for skip scan"的技术。

换句话说,尽管我们的 SQL 没有遵循最左前缀原则,仅仅使用了 f2 作为查询条件,但经过 MySQL 8.0 的优化,仍然通过索引跳跃扫描的方式利用了索引。

优化原理

那么他是怎么优化的呢?
在 MySQL 8.0.13 及以后的版本中,执行SELECT f1, f2 FROM t1 WHERE f2 = 40;的过程如下:

  1. 获取 f1 字段的第一个唯一值,即 f1=1。
  2. 构造条件f1=1 and f2=40,进行范围查询。
  3. 获取 f1 字段的第二个唯一值,即 f1=2。
  4. 构造条件f1=2 and f2=40,进行范围查询。
  5. 重复上述步骤,直到扫描完 f1 字段的所有唯一值。
  6. 最后将结果合并并返回。

换句话说,最终执行的 SQL 语句类似于下面的形式:

SELECT f1, f2 FROM t1 WHERE f1 =1 and f2 = 40
UNION
SELECT f1, f2 FROM t1 WHERE f1 =2 and f2 = 40;

即,MySQL 的优化器帮我们把联合索引中的 f1 字段作为查询条件进行查询了。

限制条件

在了解了索引跳跃扫描的执行过程后,一些聪明的读者可能会意识到,这种查询优化更适用于具有较少取值范围和低区分度的字段(比如性别),而当字段的区分度特别高时(比如出生年月日),这种查询可能会变得更慢。

因此,是否使用索引跳跃扫描,实际上取决于 MySQL 优化器经过成本预估后做出的决定。

通常情况下,这种优化技术适用于联合索引中第一个字段的区分度较低的情况。但需要注意的是,并非绝对如此。尽管一般情况下我们不太会将区分度较低的字段放在联合索引的左边,但 MySQL 提供了这样的优化方案,这说明确实存在这样的需求。

然而,我们不应该过度依赖这种优化。在建立索引时,仍然应优先考虑将区分度高且频繁查询的字段放置在联合索引的左边。

此外,在 MySQL 官网中还提到了索引跳跃扫描的其他一些限制条件:

  • 表 T 必须至少有一个联合索引,但对于联合索引(A,B,C,D),A 和 D 可以为空,但 B 和 C 必须非空。
  • 查询只能依赖于单张表,不能进行多表连接。
  • 查询中不能使用 GROUP BY 或 DISTINCT 语句。
  • 查询的字段必须是索引中的列。

如有问题,欢迎加微信交流:w714771310,备注- 技术交流  。或微信搜索【码上遇见你】。

免费的Chat GPT可微信搜索【AI贝塔】进行体验,无限使用。

好了,本章节到此告一段落。希望对你有所帮助,祝学习顺利。

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

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

相关文章

AIGC 003-Controlnet升级你的SD让图像生成更加可控!

AIGC 003-Controlnet升级你的SD让图像生成更加可控! 文章目录 0 论文工作1 论文方法2 效果 0 论文工作 ControlNet 论文 (Adding Conditional Control to Text-to-Image Diffusion Models) 提出了一种名为 ControlNet 的神经网络结构,旨在为大型文本到图…

StackExchange.Redis跑起来,为什么这么溜?

StackExchange.Redis 是一个高性能的 Redis 客户端库,主要用于 .NET 环境下与 Redis 服务器进行通信,大名鼎鼎的stackoverflow 网站就使用它。它使用异步编程模型,能够高效处理大量请求。支持 Redis 的绝大部分功能,包括发布/订阅…

创意学习剪辑利器:一键添加动图水印,轻松提升视频专业度与创意新境界!

在数字化时代,视频已成为我们生活中不可或缺的一部分。无论是学习分享、工作展示还是生活记录,视频都以其直观、生动的形式,赢得了广大用户的喜爱。然而,如何在众多的视频中脱颖而出,展现出自己的专业度和创意&#xf…

[AI OpenAI] OpenAI 安全更新

AI 首尔峰会中分享我们的实践 我们自豪地构建并发布了在能力和安全性方面都处于行业领先地位的模型。 超过一亿用户和数百万开发者依赖于我们安全团队的工作。我们将安全视为我们必须在多个时间范围内投资并取得成功的事项,从使今天的模型与我们未来预期的更具能力…

谷歌浏览器使用vue插件查看表单提交的数据

1.查看组件: 对应代码里主页面引用的组件名: 表单名称,对应组件里form表单名: 左边的层次结构: 右边层次结构:

Excel/WPS《超级处理器》同类项处理,合并同类项与拆分同类项目

在工作中处理表格数据,经常会遇到同类项处理的问题,合并同类项或者拆分同类项,接下来介绍使用超级处理器工具如何完成。 合并同类项 将同一列中的相同内容合并为一个单元格。 1)用分隔符号隔开 将AB列表格,合并后为…

Spring中@Component注解

Component注解 在Spring框架中,Component是一个通用的注解,用于标识一个类作为Spring容器管理的组件。当Spring扫描到被Component注解的类时,会自动创建一个该类的实例并将其纳入Spring容器中管理。 使用方式 1、基本用法: Co…

企业微信hook接口协议,ipad协议http,已读消息

已读消息 参数名必选类型说明uuid是String每个实例的唯一标识,根据uuid操作具体企业微信send_userid是long要发送的人idisRoom是bool是否是群消息 请求示例 {"uuid":"1753cdff-0501-42fe-bb5a-2a4b9629f7fb","send_userid":788130255…

Unity学习日志

目录 获取相机可视范围的世界坐标(2D) 视口转世界坐标和屏幕转世界坐标的区别: 屏幕转世界坐标 视口转屏幕坐标 视口转屏幕结合3D数学实现可视范围的怪物生成 transform.up游戏对象的方向问题 其实还有一种不用Translate的写法: 修改 transform.up 的行为和影响 C#抽象…

全国各城市间驾车耗时和距离矩阵数据集(更新至2022年)

数据简介:城市之间距离越远,耗时越长。经济发达地区的交通状况较好。各城市之间的驾车耗时和距离存在差异。有些城市之间的交通非常便捷,而有些城市之间的交通则较为不便。这表明中国的交通网络发展尚不平衡,需进一步优化。特别是…

Excel如何统计非数值内容行数

需要用到sum函数,具体公式如下: SUM(IF(ISNONTEXT(G4:G199),0,1))

Go 语言简介 -- 高效、简洁与现代化编程的完美结合

在现代软件开发领域,选择合适的编程语言对于项目的成功至关重要。Go 语言(又称 Golang )自 2009 年由Google发布以来,以其简洁的语法、高效的并发模型以及强大的性能,迅速成为开发者们的新宠。Go语言不仅融合了传统编译…

icloud照片怎么恢复到相册?2个方法,轻松解决烦恼

在现代生活中,照片承载着我们的回忆和珍贵的时刻,而iCloud提供了便捷的云存储服务,让用户可以方便地备份和同步手机上的照片、视频等文件。 然而,有时候我们可能会不小心删除了在iCloud上的照片,或者想要将iCloud照片…

使用B2M 算法批量将可执行文件转为灰度图像

参考论文 基于二进制文件的 C 语言编译器特征提取及识别 本实验使用 B2M 算法将可执行文件转为灰度图像,可执行文件转为灰度图的流程如图 4-3 所示。将 可执行文件每 8 位读取为一个无符号的的整型常量,一个可执行文件得到一个一维向量, …

基于51单片机多功能太阳能充电器设计

1 绪论1.1 本课题研究背景及现状 当代社会随着一些不可再生资源如煤炭,石油等日益减少,使得各国社会经济越来越受能源问题的约制,因此许多国家开始逐渐的实行“阳光计划”,开发洁净的能源如太阳能,用以成为本国经济发…

ANOVA方差分析是什么?优思学院教你如何正确使用

ANOVA(方差分析)是一种统计方法,用来研究三个或三个以上样本平均数的差异是否显著。它可以帮助研究者判断不同组间的均值是否存在统计学上的显著差异。简单来说,如果我们想比较多个不同处理或条件对某个变量的影响,ANO…

【网络层】网络攻击 ARP 欺骗

文章目录 ARP 欺骗原理实战体验 ARP 欺骗原理 ARP(地址解析协议)欺骗是一种网络攻击技术,它利用了ARP协议的工作机制来欺骗网络中的主机。ARP协议用于将IP地址转换为物理MAC地址,以便在局域网内部进行数据包的传输。ARP欺骗的基本…

微信小程序毕业设计-跑腿系统项目开发实战(附源码+演示视频+LW)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:微信小程序毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计…

可监测的到手价范围

在品牌进行电商价格监测时,对优惠信息范围的关注至关重要。优惠促销的形式多样,会直接影响到消费者最终的到手价。因此,为了更准确地计算到手价,品牌需要确保监测的促销信息尽可能全面。 不同的电商平台,其优惠形式可…

揭秘APP广告变现的高效秘诀:如何让你的APP更赚钱?

在数字化时代,APP已成为人们获取信息、娱乐休闲的重要平台。对于许多内容创作者来说,如何通过APP实现盈利,是一个亟待解决的问题。而APP广告变现项目,正是其中一种备受关注的盈利模式。那么,如何有效地利用APP广告变现…