MSQL系列(五) Mysql实战-索引最左侧匹配原则分析及实战

news2025/1/16 3:34:28

Mysql实战-索引最左侧匹配原则分析及实战

前面我们讲解了索引的存储结构,B+Tree的索引结构,以及索引最左侧匹配原则,Explain的用法,今天我们来实战一下 最左侧匹配原则

1.联合索引最左侧匹配原则

联合索引有一个最左侧匹配原则
最左匹配原则指的是,当使用联合索引进行查询时,MySQL会优先使用最左边的列进行匹配,然后再依次向右匹配。

假设我们有一个表,包含三个列:A、B、C
创建联合索引(A,B,C) 等同于创建了索引 A, 索引 (A,B), 索引 (A,B,C)

  1. 我们使用(A,B,C)这个联合索引进行查询时,MySQL会先根据列A进行匹配
  2. 再根据列B进行匹配,最后再根据列C进行匹配。
  3. 如果我们只查询了(A,B)这两个列,而没有查询列C,那么MySQL只会使用(A,B)这个前缀来进行索引匹配,而不会使用到列C
  4. 如果我们要查询 了(B,C)这两个列,而没有查询列A,那么MySQL索引就会失效,导致找不到索引,因为最左侧匹配原理
  5. 所以 我们应该尽量把最常用的列放在联合索引的最左边,这样可以提高查询效率
2.实战

新建表结构 user, user_info

#新建表结构 user
CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
  `id_card` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '身份证ID',
  `user_name` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名字',
  `age` int NOT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表'
  1. id 主键id列
  2. id_card 身份证id
  3. user_name 用户姓名
  4. age 年龄

先插入测试数据, 插入 5条测试数据

INSERT INTO `test`.`user` (`id`, `id_card`, `user_name`, `age`) VALUES (1, '11', 'aa', 10);
INSERT INTO `test`.`user` (`id`, `id_card`, `user_name`, `age`) VALUES (2, '22', 'bb', 20);
INSERT INTO `test`.`user` (`id`, `id_card`, `user_name`, `age`) VALUES (3, '33', 'cc', 30);
INSERT INTO `test`.`user` (`id`, `id_card`, `user_name`, `age`) VALUES (4, '44', 'dd', 40);
INSERT INTO `test`.`user` (`id`, `id_card`, `user_name`, `age`) VALUES (5, '55', 'ee', 50);
2.1 创建 id_card,user_name,age的索引列
alter table user add index idx_card_name_age(id_card,user_name,age);

创建索引成功
在这里插入图片描述
我们现在user表只有一个新建的索引
在这里插入图片描述

2.2. 查B,C列信息
  • (A,B,C)的联合索引, 单纯的查B, 或者查BC是无法用到索引的,走的是全部索引扫描type=index类型
    查询user_name, 查询语句中没有id_card
EXPLAIN SELECT * FROM `user` where user_name = "aa";

执行结果
在这里插入图片描述

  • (A,B,C)的联合索引, 单纯的查C,同样的结果,走的是全部索引扫描type=index类型
    查询age,查询语句中没有id_card
EXPLAIN SELECT * FROM `user` where age = 10;

执行结果
在这里插入图片描述

  • (A,B,C)的联合索引, 查BC,同样的结果,走的是全部索引扫描type=index类型
    查询user_name 和 age,查询语句中没有id_card
EXPLAIN SELECT * FROM `user` where user_name = "aa"  and age = 10;

执行结果
在这里插入图片描述

2.3查询A列的相关信息

上面我们看到了只要查询语句中不包含A的字段信息,所有的索引全都不生效,扫描全部索引信息,这不是我们想要的

这也就是最左侧匹配原则导致的,所以我们在查询的时候,一定要从最左侧开始查询,也就是查询语句一定要有A查询条件,否则索引不生效

  • (A,B,C)的联合索引, 查A,type=ref类型使用了索引,索引扫描行数rows=1,只扫描了一行,精确查找, filtered=100%,过滤占比百分百,效率很高
    只查询 id_card 字段
EXPLAIN SELECT * FROM `user` where id_card = "11" ;

执行结果
在这里插入图片描述

  • (A,B,C)的联合索引, 查A,B列,相同的结果, type=ref类型使用了索引,索引扫描行数rows=1,只扫描了一行,精确查找, filtered=100%,过滤占比百分百,效率很高
    查询 id_card 及 user_name 字段
EXPLAIN SELECT * FROM `user` where id_card = "11" and user_name = "aa" ;

执行结果
在这里插入图片描述

  • (A,B,C)的联合索引, 查A,C列,相同的结果, type=ref类型使用了索引,索引扫描行数rows=1,只扫描了一行,精确查找, filtered=20% ,过滤占比 20%,意思是所有的5索引数据,找到了1条数据
    效率不算高,也不建议这样使用
    查询 id_card 及 age 字段
EXPLAIN SELECT * FROM `user` where id_card = "11" and user_name = "aa" ;

执行结果
在这里插入图片描述

  • (A,B,C)的联合索引, 查A,B,C 列,相同的结果, type=ref类型使用了索引,索引扫描行数rows=1,只扫描了一行,精确查找, filtered=100%,过滤占比百分百,效率很高
    查询 id_card 及 user_name 及age 字段
EXPLAIN SELECT * FROM `user` where id_card = "11" and user_name = "aa" and age =10 ;

执行结果
在这里插入图片描述

  • (A,B,C)的联合索引, 查C,A,B 列,查询语句乱序, 看下查询结果,依旧是相同的结果, type=ref类型使用了索引,索引扫描行数rows=1,只扫描了一行,精确查找, filtered=100%,过滤占比百分百,效率很高
    查询 id_card 及 user_name 及age 字段, 查询条件的乱序,不会影响到索引的信息
EXPLAIN SELECT * FROM `user` where age =10  and user_name = "aa" and id_card = "11" ;

执行结果
在这里插入图片描述

  • (A,B,C)的联合索引, 查C,A,B 列,查询语句乱序, 看下查询结果,依旧是相同的结果, type=ref类型使用了索引,索引扫描行数rows=1,只扫描了一行,精确查找, filtered=100%,过滤占比百分百,效率很高
    查询 id_card 及 user_name 及age 字段, 查询条件的乱序,不会影响到索引的信息
EXPLAIN SELECT * FROM `user` where age =10  and user_name = "aa" and id_card = "11" ;

执行结果
在这里插入图片描述

3. 如何知道具体用了那个索引?

我们可以通过 explain key_len计算到底使用了那个索引字段

通过刚才的验证,我们了解不同的索引,使用的ken_len长度不同,到底这个key_len如何计算,我们如何知道到底用了那个索引?

首先看下数据库编码类型 utf8mb4 编码方式
在这里插入图片描述

然后 看下表结构
id_card notNull
user_name 允许null
age 允许null
在这里插入图片描述

然后开始计算 ken_len的长度

  • 字符集编码: 字符 如 utf8mb4 = 4 ,utf8 = 3, gbk = 2, latin1 = 1, 数字int =4位
  • 列是否为空: NULL(+1),NOT NULL(+0)
  • 列类型为字符: varchar(+2), char(+0)
    到底如何计算key_len呢? key_len = (字段长度)* 编码格式 + (notNull/null)+ 列类型, 我们看下是否真的是这样
EXPLAIN SELECT * FROM `user` where id_card = "11" ;

使用了 id_card 单个字段的索引
key_len
= (char(32)) 4 + (notNull)0 + (char)0
= 32
4 +0 +0 = 128
在这里插入图片描述

EXPLAIN SELECT * FROM `user` where user_name = "aa" and id_card = "11" ;

使用了 id_card 和 user_name 2个字段的索引, user_name允许为null +1,
key_len
= (char(32)) * 4 + (notNull)0 + (char)0 + (char(32)) 4 + (Null)1 + (char)0
= 32
4 + 32*4 +1 = 257
在这里插入图片描述

EXPLAIN SELECT * FROM `user` where user_name = "aa" and id_card = "11"  and age =10;

使用了 id_card 和 user_name 及 age 三个字段的索引, user_name允许为null +1, age允许为null +1, age类型为int,占4位
key_len
= (char(32)) * 4 + (notNull)0 + (char)0 + (char(32)) 4 + (Null)1 + (char)0 + (int)4 + (Null)1 + (int)0
= 32
4 + 32*4 +1 + 5= 262
在这里插入图片描述

没有用到某个字段的索引,ken_len不会计算它的长度,比如A,C列的查询 id_card和age的查询,不会用到age的索引,只用到了id_card,key_len只会计算 id_card的长度

EXPLAIN SELECT * FROM `user` where id_card = "11" and age=10 ;

key_len = (char(32)) * 4 + (notNull)0 + (char)0 = 128, 只用到了id_card的索引信息
在这里插入图片描述


至此,我们了解了联合索引的最左侧匹配原则,也知道了如何去优化查询语句,才能使用到索引,并且知道了key_len分析具体使用了那些索引

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

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

相关文章

一文了解什么是数字孪生

数字孪生,作为数字化时代的新兴技术,正日益引领着未来的发展方向。它并非一种独立的工具或软件,而是一种理念,一种将实体与虚拟世界紧密结合的方法。本文将详细介绍数字孪生的本质、应用领域以及对未来的影响。 数字孪生的本质 …

Redis:Feed流之Timeline的实现

当我们关注了用户后,这个用户发了动态,那么我们应该把这些数据推送给用户,这个需求,其实我们又把他叫做Feed流,关注推送也叫做Feed流,直译为投喂。为用户持续的提供“沉浸式”的体验,通过无限下…

多测师肖sir_高级金牌讲师___python之模块openpyxl

python之模块openpyxl 一、用python读写excel的强大工具:openpyxl (一)下载openpyxl的方式 方式一:python -m pip install openpyxl 或 pip install openpyxl 方式二:在pycharm中安装 (二)…

《优化接口设计的思路》系列:第五篇—接口发生异常如何统一处理

系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 本文参考项目源码地址:summo-springboot-interface-demo 前言 大家好!…

VScode运行SVN拉下来的项目

安装依赖包 pnpm install 启动程序 查看package.json文件中的serve,根据这个启动 pnpm dev 在浏览器使用http://localhost:8848/访问

论文阅读:Point-to-Voxel Knowledge Distillation for LiDAR Semantic Segmentation

来源:CVPR 2022 链接:https://arxiv.org/pdf/2206.02099.pdf 0、Abstract 本文解决了将知识从大型教师模型提取到小型学生网络以进行 LiDAR 语义分割的问题。由于点云的固有挑战,即稀疏性、随机性和密度变化,直接采用以前的蒸馏…

【算法设计与分析】第6章02 分支限界法

目录 分支限界法的设计技术 分支限界法:  约束条件  剪枝  分支限界法的设计步骤 思考题: 【例6-6】装载问题。  计算模型 【例6-7】背包  问题分析  问题分析 计算模型  计算模型  算法设计与描述 代码: 思…

文件打包下载excel导出和word导出

0.文件下载接口 请求 GET /pm/prj/menu/whsj/download/{affixId} 文件affixId多个id以逗号隔开。多个文件会以打包得形式。 1.Excel导出 1.0接口 POST 127.0.0.1:8400/pm/io/exportExcel/year-plan-table-workflow/report 参数 [{"org":"011","re…

C#快速排序算法

快速排序实现原理 快速排序(Quick Sort)是一种常用的排序算法,它基于分治的思想,通过将一个无序的序列分割成两个子序列,并递归地对子序列进行排序,最终完成整个序列的排序。 其基本思路如下: 选…

056:mapboxGL中layer的layout,paint,filter的属性值表达式说明总结

第056个 点击查看专栏目录 本篇文章是mapbox的layer中layout,paint,filter的表达式说明总结。 mapbox中 Expressions 是什么 Expressions:表达式集合(并非 style 的属性,只是 layer 的任何 layout布局属性和 paint绘制属性,以及 filter 属性等,它们的值都可以指定成一…

【NV GPU限制出口】昇腾能否接住滔天富贵

如何评价刘庆峰所言华为GPU已可对标英伟达A100? 国家超级计算济南中心: https://www.nsccjn.cn/

JAVA学习日记1——JAVA简介及第一个java程序

简单记忆 JAVA SE :标准版,核心基础 JAVA EE:企业版,进阶 JDK:Java Development Kit,Java开发工具包,包含JRE JRE:Java Runtime Environment,Java运行时环境&#xff…

Elasticsearch小bug记录:term: XXX was completely eliminated by analyzer

问题: 下面这个报错,是在配置同义词的时候报的错:不能识别南京。 {"error": {"root_cause": [{"type": "illegal_argument_exception","reason": "failed to build synonyms"…

Linux-ssh

文章目录 远程登录服务器配置远程服务器相关信息创建config文件配置config文件 配置密钥登陆先创建密钥配置密钥文件 执行命令scp传文件copy文件copy文件夹配置我们的vim和tmux 远程登录服务器 ssh userhostnameuser:用户名hostname:IP地址或域名 第一次登陆会显示…

Spring MVC(一)【什么是Spring MVC】

重点 Spring:IOC 和 AOP 。 Spring MVC :Spring MVC 的执行流程。 SSM 框架的整合! Spring 和 Mybatis 我们不建议使用太多注解,Spring MVC 建议全部使用注解开发! 1、MVC 回顾 1.1、什么是MVC MVC是模型(Model)…

音乐播放器VHDL蜂鸣器数码管显示简谱,视频/代码

名称:音乐播放器数码管显示简谱蜂鸣器 软件:Quartus 语言:VHDL 代码功能: 设计音乐播放器,播放一首歌,使用开发板的蜂鸣器播放音乐,使用Quartus内的ROM IP核存储音乐文件,使用数…

编程语言常识

看图区别编程语言 什么是强类型、弱类型语言?哪种更好? 强类型语言 强类型语言是一种强制类型定义的语言,即一旦某一个变量被定义类型,如果不经强制转换,那么它永远就是该数据类型。 在强类型语言中,变量的…

Linux考试复习整理

文章目录 Linux考试整理一.选择题1.用户的密码现象放置在哪个文件夹?2.删除文件或目录的命令是?3.显示一个文件最后几行的命令是?4.删除一个用户并同时删除用户的主目录5.Linux配置文件一般放在什么目录?6.某文件的组外成员的权限…

CUDA编程入门系列(七) GPU内存如何管理

一、内存使用 1.CUDA程序会使用GPU内存与CPU内存 2.CPU内存的分配与释放是标准的,例如new和delete,malloc与free 3.GPU上内存涉及分配和释放使用CUDA提供的库函数实现 4.CUDA/GPU内存与CPU内存的互相传输 这里主要讲全局内存与共享内存的管理 二、CPU内存 栈:有编译器自动分配释…

哪些行业需要做等保?

等保适用于各种行业,尤其是对于涉及国家安全、金融、电信、能源、交通、医疗等重点领域的机构和企业更为重要。以下是一些常见的需要进行等保的行业: 政府部门和政府机构:各级政府部门、公安、国防等机构需要对信息系统进行等级保护测评和认证…