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

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.hqwc.cn/news/140555.html

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

相关文章

【网络】计算机网络基础概念入门

🍁 博主 "开着拖拉机回家"带您 Go to New World.✨🍁 🦄 个人主页——🎐个人主页 🎐✨🍁 🪁🍁🪁🍁🪁🍁🪁&#…

Django REST Framework完整教程-RESTful规范-序列化和反序列数据-数据视图

文章目录 1.简介及安装2.案例模型2.1.创建模型2.2.安装mysql必要组件2.3.管理后台转中文2.4.启动后台 3.数据序列化4.RESTful规范4.1.协议、域名和版本4.2.uri(统一资源标识符)4.3.查增删改4.4.过滤信息(Filtering)4.5.状态码(Status Codes&a…

Godot 官方2D C#重构(1):雪花碰撞

前言 Godot 官方 教程 Godot 2d 官方案例C#重构 专栏 Godot 2d 重构 github地址 实现效果 难点介绍 Godot GDScript和C# 对应关系大部分靠猜 文件导入 资源地址:默认为res://开头2D贴图导入类型:Texture2D public Texture2D Bullet_Image new Textu…

MySQL官方文档如何查看,MySQL中文文档

这里写自定义目录标题 MySQL官方文档如何查看MySQL中文文档 MySQL官方文档如何查看 MySQL官网地址:https://dev.mysql.com/doc/ 比如这里我要找InnoDB架构 MySQL中文文档 MySQL 5.1中文文档地址:https://www.mysqlzh.com/

ZKP3.2 Programming ZKPs (Arkworks Zokrates)

ZKP学习笔记 ZK-Learning MOOC课程笔记 Lecture 3: Programming ZKPs (Guest Lecturers: Pratyush Mishra and Alex Ozdemir) 3.3 Using a library ( tutorial) R1CS Libraries A library in a host language (Eg: Rust, OCaml, C, Go, …)Key type: constraint system Mai…

关于opencv的contourArea计算方法

cv::contourArea计算的轮廓面积并不等于轮廓点计数,原因是cv::contourArea是基于Green公式计算 老外的讨论 github 举一个直观的例子,图中有7个像素,橙色为轮廓点连线,按照contourArea的定义,轮廓的面积为橙色所包围…

小程序:uniapp解决主包体积过大的问题

已经分包但还是体积过大 运行时勾选“运行时是否压缩代码”进行压缩 在manifest.json配置(开启分包优化) "mp-weixin" : {"optimization" : {"subPackages" : true}//.... },在app.json配置(设置组件按需注入…

Android查看签名信息系列 · 使用Android Studio获取签名

前言 Android查看签名信息系列 之使用Android Studio获取签名,通过Android Studio自带的gradle来获取签名信息。 优点:此法可查看 MD5、SHA1 等信息。 缺点:升级某个Studio版本后,没有签名任务了,特别不方便。 实现…

GPT4 Advanced data analysis Code Interpreter 做行业数据分析、可视化处理图像、视频、音频等

1. 跨境电商如何用ChatGPT选品 ChatGPT Jungle scout 案例:跨境电商如何用ChatGFT选品 ChatGPTJungle scout 素材和资料来自: Jungle ScoutEM, Michael Soltis 和 文韬武韬AIGC 1.1 从Jungle scout上下载数据 Date Range > Last 90 days Downlo…

Kafka三种认证模式,Kafka 安全认证及权限控制详细配置与搭建

Kafka三种认证模式,Kafka 安全认证及权限控制详细配置与搭建。 Kafka三种认证模式 使用kerberos认证 bootstrap.servers=hadoop01.com:9092,hadoop02.com:9092,hadoop03.com:9092,hadoop04.com:9092 security.

零基础入门网络渗透到底要怎么学?_网络渗透技术自学

前言: 很多朋友问我,想搞网络安全,编程重要吗,选什么语言呢? 国内其实正经开设网络安全专业的学校很少,大部分同学是来自计算机科学、网络工程、软件工程专业的,甚至很多非计算机专业自学的。…

计算机视觉开源代码汇总

1.【基础网络架构】Regularization of polynomial networks for image recognition 论文地址:https://arxiv.org/pdf/2303.13896.pdf 开源代码:https://github.com/grigorisg9gr/regularized_polynomials 2.【目标检测:域自适应】2PCNet: Two-Phase Cons…