Mysql索引相关学习笔记:B+ Tree、索引分类、索引优化、索引失效场景及其他常见面试题

前言

索引是Mysql中常用到的一个功能,可以大大加快查询速度,同时面试中也是经常碰到。本文是学习Mysql索引的归纳总结。

索引采用的数据结构——B+ 树

本部分主要是参考自小林Coding

B+树的由来

二分查找可以每次缩减一半,从而提高查找效率。

但是二分查找,若使用线性结构,每次插入,都是需要移动其余剩下的全部元素,消耗巨大。

因此有了二分查找树。

但是二叉树若每次插入的都比其父节点大,则会演变为链表,从而使查询复杂度从 O(logn)降低为 O(n)。

因此有了自平衡二叉树,诸如AVL树或红黑树,其都是这样的自平衡二叉树。

但由于其本质还是一棵二叉树,所以会随着数据量增大,导致层数增加, IO操作增多(每一层IO多一次)。

因此有了B树。其每个节点允许有M个子节点,M是B树的阶,假设M为3,那就是阶为3的B树,其每个节点最多有2(M-1)个数据和3(M)个子节点。若超过,则分裂节点。
在这里插入图片描述

但是 B 树的每个节点都包含数据(索引+记录),每次IO都会需要查询到节点上记录的内容。若数据量大于索引的大小,那么在读取底层节点索引的时候,就会导致较多的IO操作。从而使性能受到巨大影响。

因此有了B+ 树,B+树和B树的结构其实相似,只是仅将数据存储在底层叶子节点。其余的子节点仅存储索引。从而解决了数据大、影响IO的问题。
其次,其底层叶子节点之间,既存了索引也存了记录。叶子节点之间通过链表连接起来。从而对于范围查询,可以大大提升效率。

B+树的结构

关于B++树的结构看图就好了。
在这里插入图片描述
在这里插入图片描述

B+树的叶子节点是单链表还是双向链表

网上很多探讨针对于“其叶子节点是单向链表还是双向链表”,包括小林也是做出了一次纠正。
在此文发现了一些结论与有趣的探讨。

在这里插入图片描述

顺着此,找到了一个结论——B+ 树中各个页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的。

在这里插入图片描述

为什么选用了B+ 树

这里直接复制小林的结论了。

B+ 树 vs B 树

B+Tree 只在叶子节点存储数据,而 B 树 的非叶子节点也要存储数据,所以 B+Tree 的单个节点的数据量更小,在相同的磁盘 I/O 次数下,就能查询更多的节点。

另外,B+Tree 叶子节点采用的是双链表连接,适合 MySQL 中常见的基于范围的顺序查找,而 B 树无法做到这一点。

B+ 树 vs 二叉树

对于有 N 个叶子节点的 B+Tree,其搜索复杂度为O(logdN),其中 d 表示节点允许的最大子节点个数为 d 个。

在实际的应用当中, d 值是大于100的,这样就保证了,即使数据达到千万级别时,B+Tree 的高度依然维持在 3~4 层左右,也就是说一次数据查询操作只需要做 3~4 次的磁盘 I/O 操作就能查询到目标数据。

而二叉树的每个父节点的儿子节点个数只能是 2 个,意味着其搜索复杂度为 O(logN),这已经比 B+Tree 高出不少,因此二叉树检索到目标数据所经历的磁盘 I/O 次数要更多。

B+ 树 vs Hash

Hash 在做等值查询的时候效率贼快,搜索复杂度为 O(1)。

但是 Hash 表不适合做范围查询,它更适合做等值的查询,这也是 B+Tree 索引要比 Hash 表索引有着更广泛的适用场景的原因。

索引的分类

概述

按「数据结构」分类:B+tree索引、Hash索引、Full-text索引。

按「物理存储」分类:聚簇索引(主键索引)、二级索引(辅助索引)。

按「字段特性」分类:主键索引、唯一索引、普通索引、前缀索引。

按「字段个数」分类:单列索引、联合索引。

B+ Tree vs Hash vs Full-text

B+ Tree就是现在常用到的那样,详细见上文。

Hash在上文的最后一点也提到过,效率更快,但是不适合范围查询。其中InnoDB引擎不支持,只有Memory引擎可以使用。InnoDB引擎中,有“自适应哈希索引”。具体见此文。

Full-text索引是更罕见的,甚至于小林Coding都没有写…具体见此文。说一个适用场景:搜索引擎的全文搜索。

聚簇索引 vs 二级索引(辅助索引)

聚簇索引就是如上文B++ Tree中写的那样,放一起。

二级索引与之相对,叶子节点中存放的也仅仅是数据的位置。真正需要时候,再通过回表操作去查找。在聚簇索引之上所建立的索引,都叫做二级索引(辅助索引)

在这里插入图片描述

将数据存储于索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据,这也就是为什么索引不在key buffer命中时,速度慢的原因

这段对二级索引调用的描述感觉更加清晰。来源此文,里面也有相关更详细的讲解。

主键索引 vs 唯一索引 vs 普通索引 vs 前缀索引

· 主键索引:是在唯一索引的基础上又增加了不为空的约束(换言之,添加了唯一索引的字段,是可以包含NULL值的),即NOT NULL+UNIQUE,一张表里最多只有一个主键索引,当然一个主键索引中可以包含多个字段。

· 唯一索引:是在普通索引的基础上增加了数据唯一性的约束,一张表中可以同时存在多个唯一索引。

· 普通索引:是最基础的索引,这种索引没有任何的约束作用,它存在的主要意义就是提高查询效率。

· 前缀索引:前缀索引也叫局部索引,比如给身份证的前 10 位添加索引,类似这种给某列部分信息添加索引的方式叫做前缀索引。

单列索引 vs 联合索引

概念

单列索引:只在一个列上的索引被称作单列索引。一个表可以有多个单列索引,但这不是组合索引。

组合索引:两个或更多个列上的索引被称作组合索引,组合索引又叫联合索引。

在这里插入图片描述

最左前缀原则——按照最左优先的方式进行索引的匹配。

如果创建了一个 (a, b, c) 联合索引,如果查询条件是以下这几种,就可以匹配上联合索引:

where a=1;
where a=1 and b=2 and c=3;
where a=1 and b=2;
需要注意的是,因为有查询优化器,所以 a 字段在 where 子句的顺序并不重要。

但是,如果查询条件是以下这几种,因为不符合最左匹配原则,所以就无法匹配上联合索引,联合索引就会失效:

where b=2;
where c=3;
where b=2 and c=3;

因为(a, b, c) 联合索引,是先按 a 排序,在 a 相同的情况再按 b 排序,在 b 相同的情况再按 c 排序。所以,b 和 c 是全局无序,局部相对有序的,这样在没有遵循最左匹配原则的情况下,是无法利用到索引的。

索引优缺点(什么时候适合创建、不适合创建)

优缺点

优点——加快查询速度。

缺点:
1、需要占用物理空间,数量越大,占用空间越大。
2、创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增大。
3、会降低表的增删改的效率,因为每次增删改索引,B+ 树为了维护索引有序性,都需要进行动态维护。

是否创建

适合创建的场景

字段有唯一性限制的,比如商品编码;
经常用于 WHERE 查询条件的字段,这样能够提高整个表的查询速度,如果查询条件不是一个字段,可以建立联合索引。
经常用于 GROUP BY 和 ORDER BY 的字段,这样在查询的时候就不需要再去做一次排序了,因为我们都已经知道了建立索引之后在 B+Tree 中的记录都是排序好的。
⼤表中的关键列: 在⼤表中,如果查询的效率变得很低,可以考虑在关键列上创建索引。
表与表连接用于多表联合查询的约束条件的字段应当建立索引。

不适合创建的场景

⼩表: 对⼩表创建索引可能会带来额外的开销,因为在⼩数据集中扫描整个表可能⽐使⽤索引更快。

频繁的插⼊、更新和删除操作: 索引的维护成本会随着数据的插⼊、更新和删除操作⽽增加。如果表经常被修改,过多的索引可能会影响性能。

数据重复且分布平均的表字段:假如⼀个表有10万⾏记录,性别只有男和⼥两种值,且每个值的分布概率⼤约为50%,那么对这种字段建索引⼀般不会提⾼数据库的查询速度。MySQL 还有一个查询优化器,查询优化器发现某个值出现在表的数据行中的百分比很高的时候,它一般会忽略索引,进行全表扫描。

很少被查询的列: 如果某列很少被⽤于查询条件,那么为它创建索引可能没有明显的性能提升。

查询结果总⾏数较少的表: 如果查询的结果集总⾏数很少,使⽤索引可能不会有太⼤的性能提升

索引失效的情景

1、like %的模糊匹配。like %xx 或者 like %xx%会导致失效,like 'xx%'不会。原因是类似于姓名,根据首字母排序,但名字第二三个字的顺序没有关联。

2、对索引使用函数/表达式运算。因为索引中存储的是原始数据,而不是处理后的字段,所以不能走索引查询。

3、对索引隐式转换。因为隐式转换等同于用了函数。

4、联合索引的非最左匹配。详细见上方讲解处,就是类似于姓名排序是按照的首字母,后面的字母无关联。

5、where语句中or的多个条件,其中一个不是索引列。

在这里插入图片描述

索引优化

见此文

1)如果MySQL估计使用索引比全表扫描还慢,则不会使用索引。

2)前导模糊查询不能命中索引。

3)数据类型出现隐式转换的时候不会命中索引,特别是当列类型是字符串,一定要将字符常量值用引号引起来。

4)复合索引的情况下,查询条件不包含索引列最左边部分(不满足最左原则),不会命中符合索引。

5)union、in、or都能够命中索引,建议使用in。

6)用or分割开的条件,如果or前的条件中列有索引,而后面的列中没有索引,那么涉及到的索引都不会被用到。

7)负向条件查询不能使用索引,可以优化为in查询。
负向条件有:!=、<>、not in、not exists、not like等。

8)范围条件查询可以命中索引。范围条件有:<、<=、>、>=、between等。

9)利用覆盖索引进行查询,避免回表。
被查询的列,数据能从索引中取得,而不用通过行定位符row-locator再到row上获取,即“被查询列要被所建的索引覆盖”,这能够加速查询速度。

10)建立索引的列,不允许为null。
单列索引不存null值,复合索引不存全为null的值,如果列允许为null,可能会得到“不符合预期”的结果集,所以,请使用not null约束以及默认值。

部分面试题补充

此部分参考自此文。不得不说还是java社区资源多…

在这里插入图片描述

非聚簇索引一定会回表查询吗?

不一定。如果涉及到查询语句所要求的字段,全部命中了索引,那么就不必再进行回表查询。

举个简单的例子,假设我们在员工表的年龄上建立了索引,那么当进行select score from student where score > 90的查询时,在索引的叶子节点上,已经包含了score 信息,不会再次进行回表查询。

关于索引下推

此部分详细见此文

简单来说,(https://zhuanlan.zhihu.com/p/121084592)如果没有使用,那么流程是:检索到数据,返回Mysql服务器,判断是否符合。

如果使用了,则是:检索到数据,存储引擎判断是否符合,符合了再返回。

索引条件下推优化可以减少存储引擎查询基础表的次数,也可以减少MySQL服务器从存储引擎接收数据的次数。

为什么推荐使用自增主键作为索引?

结合B+Tree的特点,自增主键是连续的,在插入过程中尽量减少页分裂,即使要进行页分裂,也只会分裂很少一部分。并且能减少数据的移动,每次插入都是插入到最后。总之就是减少分裂和移动的频率。

参考资源

https://blog.csdn.net/qq_43592352/article/details/127351846

https://xiaolincoding.com/mysql/index/index_interview.html#%E6%8C%89%E5%AD%97%E6%AE%B5%E7%89%B9%E6%80%A7%E5%88%86%E7%B1%BB

https://mp.weixin.qq.com/s/lEx6iRRP3MbwJ82Xwp675w

https://tech.meituan.com/2014/06/30/mysql-index.html

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

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

相关文章

对话框与多窗体设计 —— 标准对话框

三、对话框与多窗体设计3.1 标准对话框3.1.1 QFileDialog对话框3.1.2 QColorDialog对话框3.1.3 QFontDialog对话框3.1.4 QInputDialog标准输入对话框3.1.5 QMessageBox消息对话框 三、对话框与多窗体设计 一个完整的应用程序设计中&#xff0c;不可避免地会涉及多个窗 体、对框…

vue---打印本地当前时间Demo

<template><view class"content" tap"getCurrentTime()">打印时间</view> </template><script>export default {data() {return {title: Hello}},onLoad() {},methods: {getCurrentTime() {//获取当前时间并打印var _this …

springboot127基于Springboot技术的实验室管理系统

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

Elasticsearch内核解析 - 数据模型篇

Elasticsearch内核解析 - 数据模型篇 - 知乎 Elasticsearch是一个实时的分布式搜索和分析引擎&#xff0c;它可以帮助我们用很快的速度去处理大规模数据&#xff0c;可以用于全文检索、结构化检索、推荐、分析以及统计聚合等多种场景。 Elasticsearch是一个建立在全文搜索引擎…

蓝牙 | 软件: Qualcomm BT Audio 问题分析(1)----ACAT Tools安装

大家好&#xff01; 我是“声波电波还看今朝”成员的一位FAE Devin.wen&#xff0c;欢迎大家关注我们的账号。 今天给大家大概讲解“如何排查Qualcomm BT Audio”的疑难杂症&#xff08;一&#xff09;如何安装ACAT Tools。 大家在遇到Audio方面的问题&#xff0c;比如 无声、…

[蓝桥杯]真题讲解:飞机降落(DFS枚举)

[蓝桥杯]真题讲解&#xff1a;飞机降落&#xff08;DFS枚举&#xff09; 一、视频讲解二、暴力代码&#xff08;也是正解代码&#xff09; 一、视频讲解 视频讲解 二、暴力代码&#xff08;也是正解代码&#xff09; //飞机降落&#xff1a; 暴力枚举DFS #include<bits/…

【python】自动微分的一个例子

一、例子 import torchx torch.arange(4.0) x.requires_grad_(True) y 2 * torch.dot(x, x) print(y) y.backward() x.grad 4 * x print(x.grad) 二、解读 1. import torch 这一行导入了PyTorch库。PyTorch是一个开源的机器学习库&#xff0c;广泛用于计算机视觉和自然语…

DAY10_SpringBoot—SpringMVC重定向和转发RestFul风格JSON格式SSM框架整合

目录 1 SpringMVC1.1 重定向和转发1.1.1 转发1.1.2 重定向1.1.3 转发练习1.1.4 重定向练习1.1.5 重定向/转发特点1.1.6 重定向/转发意义 1.2 RestFul风格1.2.1 RestFul入门案例1.2.2 简化业务调用 1.3 JSON1.3.1 JSON介绍1.3.2 JSON格式1.3.2.1 Object格式1.3.2.2 Array格式1.3…

一站式VR全景婚礼的优势表现在哪里?

你是否想过&#xff0c;婚礼也可以用一种全新的方式呈现&#xff0c;VR全景婚礼让每位用户沉浸式体验婚礼现场感。现在很多年轻人&#xff0c;都想让自己的婚礼与众不同&#xff0c;而VR全景婚礼也是未来发展的方向之一。 很多婚庆公司开通了VR婚礼这一服务&#xff0c;就是通过…

YOLOv5改进系列(28)——添加DSConv注意力卷积(ICCV 2023|用于管状结构分割的动态蛇形卷积)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制

mysql生成最近24小时整点最近30天最近12个月时间临时表

文章目录 生成最近24小时整点生成最近30天生成最近12个月 在统计的时候需要按时间来展示&#xff0c;但是数据的时间不一定是连续的&#xff0c;那就需要在代码里面生成连续的时间&#xff0c;然后按时间匹配到对应的数据&#xff0c;这样比较麻烦&#xff0c;可以在sql中使用连…

统计学-R语言-6.3

文章目录 前言总体方差的区间估计总体方差的区间估计(一个总体方差的估计)总体方差的区间估计(两个总体方差比的估计) 总结 前言 本篇文章是最后一个介绍参数估计的章节。 总体方差的区间估计 研究一个总体时&#xff0c;推断总体方差 使用的统计量为样本方差 。研究两个总体…

antdesignvue中使用VNode写法

1、使用场景 如图&#xff1a;消息提示框中&#xff0c;将数据中的数据单独一行显示 2、代码 let errorList res.result; //后端返回的数据例&#xff1a; ["1. 数据格式不正确","2. 数据已存在"]if(errorList&&errorList.length!0){this.$notif…

SpringCloud Bus动态刷新全局广播

文章目录 代码地址配置项目配置修改测试 SpringCloud Bus动态刷新定点通知 代码地址 地址:https://github.com/13thm/study_springcloud/tree/main/days11_%20Bus 配置项目 必须先具备良好的RabbitMQ环境先 演示广播效果&#xff0c;增加复杂度&#xff0c;再以3355为模板再…

node多版本管理工具nvm安装

开发前端项目&#xff0c;有时候新老项目交替&#xff0c;不同项目需要不同的node.js&#xff0c;本机电脑需要安装多个版本的nodejs&#xff0c;手动切换十分麻烦&#xff0c;有了nvm就可以轻松解决这个问题&#xff0c;nvm全名node.js version management 它是一个nodejs的版…

软考复习之UML设计篇

UML统一建模语言 构件图&#xff1a;描述系统的物理结构&#xff0c;它可以用来显示程序代码如何分解成模块 部署图&#xff1a;描述系统中硬件和软件的物理结构&#xff0c;它描述构成系统架构的软件构件&#xff0c;处理器和设备 用例图&#xff1a;描述系统与外部系统及用…

python使用回溯算法解决括号组合问题

对于给定k为括号的总对数&#xff0c;需要将能够组合的所有有效括号组合方式求出的问题。 对于回溯算法是将解空间看做一定的结构&#xff0c;通常是作为树形结构或者图形结构&#xff0c;回溯算法实际上是一种类似枚举的探索尝试过程&#xff0c;主要是在探索尝试过程中寻找解…

c++:类和对象(5),运算符重载

目录 运算符重载概念&#xff1a; 运算符重载 1.成员函数重载号 2.全局函数重载号 打印结果&#xff1a; <<运算符重载 递增运算符重载 简单例子 输出结果为&#xff1a; 赋值运算符重载 如何重载 输出结果为&#xff1a; 什么时候重载 关系运算符重载 简单例…

springboot121编程训练系统设计与实现

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的编程训练系统设计与实现 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四…

一文深度解读多模态大模型视频检索技术的实现与使用

当视频检索叠上大模型Buff。 万乐乐&#xff5c;技术作者 视频检索&#xff0c;俗称“找片儿”&#xff0c;即通过输入一段文本&#xff0c;找出最符合该文本描述的视频。 随着视频社会化趋势以及各类视频平台的快速兴起与发展&#xff0c;「视频检索」越来越成为用户和视频平…