MySQL索引,你真的学会了?索引底层原理是什么?索引什么时候失效,你知道吗?

目录

1、什么是索引

2、索引分类

3、索引的基本操作

3.1、主键索引

3.2、单列索引

3.3、唯一索引

3.4、复合索引

4、索引的底层原理

        为什么使用B+Tree而不是B-Tree?

如果数据量特别大的情况下,B+Tree会不会深度太深影响查询效率?

5、聚簇索引和非聚簇索引

5.1、概念:

5.2、使用聚簇索引的优势

5.3、聚簇索引需要注意什么

5.4、为什么通常建议使用自增id

6、索引失效的常见场景


 

1、什么是索引

1.1、索引定义 

        索引是一种帮助MySQL提高查询效率的数据结构

1.2、索引的优点

        加快数据查询的速度

1.3、索引的缺点

  1. 维护索引需要耗费数据库资源
  2. 索引需要占用磁盘空间
  3. 当对表的数据进行增删改时,因为要维护索引,速度会受到影响

2、索引分类

  1. 主键索引:设定为主键后数据库会自动建立索引,innodb为聚簇索引
  2. 单值索引:一个索引只包含一个列,一个表可以有多个单列索引
  3. 唯一索引:索引列的值必须唯一,但允许有空值
  4. 复合索引:一个索引包含多个列

3、索引的基本操作

3.1、主键索引

建表,把id设置为主键:

e52f18f4b5b64eb0b52f8568a7aacafd.png

查看索引:

868e742d2eaa4f42b27fb343cbdd352a.png

可以看到,我们没有设置索引,但数据库已经自动帮我们把主键设置为索引了~

3.2、单列索引

建表,把age设置为单列索引:

aacfc8d2636848ffb16f7c6ade051e8e.png

        通过上述,我们可以观察到,主键被数据库自动设置为索引,单列索引可以和主键索引同时存在~

3.3、唯一索引

建表,把name设置为唯一索引:

5f44443cf63849feb6142e3b8b1c9f4e.png

唯一索引和主键索引的区别:

8b61fa5ecf17427ba646b3ab05a4a45f.png

主键索引的值不能为空,而唯一索引的值可以为空(我在MySQL5.7版本上是支持多个数据为空的的)~

3.4、复合索引

建表,把name和age设置为复合索引:

57e3cdb206544c40b84aabe3290299f4.png

复合索引底层如何存储的,我们先来看看索引的底层原理:


4、索引的底层原理

在MySQL中,实际存储数据,是如何存储的呢?

如下:

476b45629089496bbee4bcb4a927b4e5.png

看上图,我们会知道存储数据时,是按照三部分存储的,一个是主键索引,一个是数据部分,一个是指针。那么指针指向哪里呢?指针是指向下一个节点的:

6f2ea8d027064518bd25eea5b5d848a5.png

        数据就是这样组织起来的。有一个点需要注意的是,MySQL索引底层的数据是按照主键进行有序放置的,也就是说,数据是按照主键索引进行有序存储的。那么问题来了,当我们存入的数据特多时,我们是需要把数据全部遍历一遍吗?这样的话,时间复杂度是不是有点太大了,如果有一万个数据,运气不好的话,找数据不是得找一万次?

        那根据我们上述所说的数据是按照主键有序存储的,那我们就可以对底层数据存储进行优化,把数据划分成一个个的区域,例如下面的3个数据一划分:

af3da16e87dc425eb51291f6cdfde14e.png

       

        划分后,我们就可以把每个区域看成是一页页的数据(MySQL中,每一页默认是规定存储16KB的数据),我们就可以给每一页数据一个目录,如下:

2bbddb8075854ba3be991a2c0859c07a.png

        观察上图,我们就可以得知,目录中的数据其实就是每一页的数据的第一个数据~

        细心的小伙伴会发现,目录中存储的数据,并不是完整的数据,而是只存放了一个数据的主键和指针~

        如果说,如果数据量非常非常大,目录这个区域也已经超过了16KB的数据怎么办,是不是需要我们再给目录再提一层目录呢~如下:

0f44f621d8c7493897b52d43c50d1699.png

        此时,看到这里学习过数据结构的小伙伴就会知道,这个不就是B+树吗?对的,MySQL索引就是采用了B+的数据结构。

        B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构,InnoDB存储引擎(Mysql的默认引擎就是InnoDB)就是用B+Tree实现其索引结构。

        为什么使用B+Tree而不是B-Tree?

  1. B+Tree的非叶子节点只存储键值信息,而B-Tree是存储所有数据(每一页的存储空间是有限的,如果非叶子节点也存储数据,会导致每个节点能存储的key的数量变少;当存储的数据量很大时,会导致T-Tree的深度变大,增加查询时的磁盘I/O次数,进而影响查询效率;而B+Tree就能很好的解决这些问题)
  2. B+Tree所有叶子结点之间都有一个链指针,B-Tree没有
  3. B+Tree数据记录都存放在叶子结点中

如果数据量特别大的情况下,B+Tree会不会深度太深影响查询效率?

        不会哦~B+Tree的高度一般都是在2~4层,而MySQL的InnoDB存储引擎在设计时,是将根节点常驻内存的,也就是说,查找某一键值的行记录时最多只需要1~3次磁盘I/O操作~

        为什么B+Tree的高度一般都是在2~4层?

我们可以来算一算一页能存放多少数据:

        假设是我们刚才的数据的表,有一个id,一个name,一个age。id是int类型,4个字节(数据量大时,需要使用bigInt,8个字节);name假设是设置20字节;age为int类型,4个字节;一个指针,8个字节;一共一条数据36字节。

1KB=1024字节;一页可以存16KB,16*1024/28约等于455条数据。

当我们的B+Tree的高度为2时,也就是说有一层目录,我们来算算能存多少数据:

        目录中,只存放id和指针,一共12个字节,一页能存放数据个数:16*1024/12约等于1365个数据。那么1365的数据就对应1365页叶子节点的数据,约等于对应621226条数据。

        当B+Tree的高度为3时,大家可以自己算算,能存的数据量其实是非常大的,因此一般B+Tree的高度都是在2~4层的~


5、聚簇索引和非聚簇索引

5.1、概念:

  • 聚簇索引:将数据存储与索引放到一块,索引结构的叶子结点保存了行数据
  • 非聚簇索引:将数据与索引分开存储,索引结构的叶子结点指向了数据对应的位置。

聚簇索引:

        也就是说,数据库中的所有数据都是放在聚簇索引的叶子结点中的,而其他索引都属于辅助索引(例如:复合索引、前缀索引、唯一索引等),辅助索引叶子结点中存储的不是数据的物理位置,而是主键值,因此,辅助索引访问数据时总是需要二次查找的:

f7bf992a218e4316a2dc2e187e9c72c5.png

说明: 

  1. 我们会看到辅助索引,是以age作为单列索引的,索引这个索引树就是以age大小排序的~
  2. InnoDB使用的是聚簇索引,将主键组织到一B+树中,而行数据就储存在叶子节点上,若使用 where d =4"这样的条件查找主键,则按照B+树的检索算法即可查找到对应的叶节点,之后获得行数据。
  3. 若对Name列进行条件搜索,则需要两个步: 第一步在辅助索引B+树中检索Name,到达其叶子节点获取对应的主键,第二步使用主键在主索引B+树种再执行一次B+树检索操作,最终到达叶子节点即可获取整行数据。 (重点在于通过其他键需要建立辅助索引)
  4. 聚簇索引默认是主键,如果表中没有定义主键,InnoDB 会选择一个唯一且非空的索代,如果没有这样的索引,InnoDB 会隐式定义一个主键(举似oracle中的Rowld)来作为聚索引,如果已经设置了主键为聚索引又希望再单独设置聚索引,必须先别除主键,然后添加我们想要的聚能索引,最后恢复设置主键即可。

非聚簇索引:

        MYISAM就是使用的非聚簇索引,非聚簇索引的两颗B+树看上去没有什么不同,节点的结构完全一致,只是存储的内容不同。主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子结点都使用一个地址指向真正的表数据,对于表数据来说,这两个建没有任何差别,由于索引树是独立的,通过辅助建索引无需访问主键的索引树:

43b2735ff555418a809a1b1f26f48b36.png

5.2、使用聚簇索引的优势

        每次使用辅助索引检索都要经过两次B+树查找,看上去聚簇索引的效率明显要低于非聚簇索引,这不是多此一举吗?聚簇索引的优势在哪?

  1. 由于行数据和聚簇索引的叶子节点存储在一起,同一页中会有多条行数据,访问同一数据页不同行记录时,已经把页加载到了Buffer中(缓存器),再次访问时,会在内存中完成访问,不必访问磁盘。这样主键和行数据是一起被载入内存的,找到叶子节点就可以立刻将行数据返回了,如果按照主键Id来组织数据,获得数据更快。
  2. 辅助索引的叶子节点,存储主键值,而不是数据的存放地址。好处是当行数据放生变化时,索引树的节点也需要分裂变化;或者是我们需要查找的数据,在上一次IO读写的缓存中没有,需要发生一次新的IO操作时,可以避免对辅助索引的维护工作,只需要维护聚簇索引树就好了。另一个好处是,因为辅助索引存放的是主键值,减少了辅助索引占用的存储空间大小。

5.3、聚簇索引需要注意什么

        当使用主键为聚簇索引时,主键最好不要使用UUID,因为UUID的值太过于离散,不适合排序且可能出现新增记录的UUID,会插入在索引树中间的位置,导致索引树调整复杂度变大,消耗更多的时间和资源。

        建议使用int类型的自增,方便排序并且默认会在索引树的末尾增加主键值,对索引树的结构影响最小。而且,逐渐值占用的存储空间越大,辅助索引中保存的主键值也会跟着变大,占用存储空间,也会影响到IO操作读取到的数据量~

5.4、为什么通常建议使用自增id

        聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻的存放在磁盘上的。如果主键不是自增id,那么可以想象,例如使用UUID,每次都是随机值,就会导致每次添加数据时,都不要不断地调整数据的物理地址、重新分页等。当然也有其他措施来减少这些操作,但是这是无法减少这些操作的,但却无法彻底避免。那如果说使用自增,那就简单了,他只需要一页一页的写,索引结构相对紧凑,磁盘碎片少,效率也高~


6、索引失效的常见场景

  • 复合索引(联合索引),要使用最左前缀(也就是说,联合索引,索引的叶子结点在排序时其实是按照创建索引时,最左边这个值排序的,因此要使用最左前缀),否则会失效
  • 查询时使用like关键字,并且以%开头时,索引会失效
  • 在列上进行函数运算时,索引会失效
  • 使用in不会造成索引失效,而not in会
  • 使用or关键字时,如果or的前后的列都是索引则会使用索引,如果其中一个列不是索引,索引就会失效~

好啦,本期就到这里咯,下期见~~~

 

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

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

相关文章

OpenGL_Learn15(投光物)

1. 平行光 cube.vs******************#version 330 core layout (location 0) in vec3 aPos; layout (location 1 ) in vec3 aNormal; layout (location2) in vec2 aTexCoords;out vec3 FragPos; out vec3 Normal; out vec2 TexCoords;uniform mat4 model; uniform mat4 view…

车牌识别 支持12种中文车牌类型 车牌数据集下载

开源代码 如果觉得有用,不妨给个Star⭐️🌟支持一下吧~ 谢谢! Acknowledgments & Contact 1.WeChat ID: cbp931126 2.QQ Group:517671804 加微信(备注:PlateAlgorithm),进讨论群可以获得10G大小的车牌检测和识…

DPAFNet:一种用于多模式脑肿瘤分割的残差双路径注意力融合卷积神经网络

DPAFNet: A Residual Dual-Path Attention-Fusion Convolutional Neural Network for Multimodal Brain Tumor Segmentation DPAFNet:一种用于多模式脑肿瘤分割的残差双路径注意力融合卷积神经网络背景贡献实验方法ulti-scale context feature extraction block&…

【Spring】之IoC与对象存取

未来的几周时间,大概率我会更新一下Spring家族的一些简单知识。而什么是Spring家族,好多同学还不是很清楚,我先来简单介绍一下吧: 所谓Spring家族,它其实就是一个框架,是基于Servlet再次进行封装的内容。为…

VMware——WindowServer2012R2环境安装mysql5.7.14解压版_互为主从(图解版)

目录 一、服务器信息二、192.168.132.35服务器上安装mysql(主)2.1、环境变量配置2.2、安装2.2.1、修改配置文件内容2.2.2、初始化mysql并指定超级用户密码2.2.3、安装mysql服务2.2.4、启动mysql服务2.2.5、登录用户管理及密码修改2.2.6、开启远程访问 三…

C++函数

转载知呼大佬06 - C函数 - 知乎 (zhihu.com) 06 - C函数 本期我们讨论的是 C 中的函数。 函数到底是什么呢,函数就是我们写的代码块,被设计用来执行特定的任务,以后我们学习 class 类的时候,这些块会被称为方法,但是…

windows电脑连接Android和iPhone真机调试

windows电脑连接Android和iPhone真机调试 目前用的是Hbuilder X编辑器,在正常情况下,Android手机需要在 "设置 ----> 更多设置 ----->关于手机 ------> 版本号(手指点击5-7下即可打开开发者模式)"(我的是vivo的…

MATLAB | 绘图复刻(十三) | 带NaN图例的地图绘制

有粉丝问我地图绘制如何添加NaN,大概像这样: 或者这样: 直接上干货: 原始绘图 假设我们有这样的一张图地图,注意运行本文代码需要去matlab官网下载Mapping Toolbox工具箱,但是其实原理都是相似的&…

人工智能基础_机器学习046_OVR模型多分类器的使用_逻辑回归OVR建模与概率预测---人工智能工作笔记0086

首先我们来看一下什么是OVR分类.我们知道sigmoid函数可以用来进行二分类,那么多分类怎么实现呢?其中一个方法就是使用OVR进行把多分类转换成二分类进行计算. OVR,全称One-vs-Rest,是一种将多分类问题转化为多个二分类子问题的策略。在这种策略中,多分类问题被分解为若干个二…

计算机毕业设计 基于SpringBoot的社区物资交易互助平台/系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍:✌从事软件开发10年之余,专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ 🍅文末获取源码联系🍅 👇🏻 精…

【C++】泛型编程 ⑩ ( 类模板的运算符重载 - 函数实现 写在类外部的同一个 cpp 代码中 | 类模板 的 外部友元函数二次编译问题 )

文章目录 一、类模板 - 函数声明与函数实现分离1、类模板 外部 实现 构造函数2、类模板 外部 实现 普通函数3、类模板 外部 实现 友元函数( 1 ) 错误示例及分析 - 类模板 的 外部友元函数 二次编译 问题( 2 ) 正确写法 二、代码示例 - 函数声明与函数实现分离1、代码示例2、执行…

level=warning msg=“failed to retrieve runc version: signal: segmentation fault“

安装docker启动后,发现里面没有runc版本信息 目前看是少了runc组件 那我们安装runc https://github.com/opencontainers/runc/releases/download/v1.1.10/runc.amd64 [rootlocalhost ~]# mv runc.amd64 /usr/bin/runc mv:是否覆盖"/usr/bin/runc&q…

Git 分支管理

目录 列出分支 删除分支 分支合并 合并冲突 几乎每一种版本控制系统都以某种形式支持分支,一个分支代表一条独立的开发线。 使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。 Git 分支实际上是指向更改快照的指针。 有…

修复dinput8.dll丢失的简单方法,解决dinput8.dll丢失

在使用电脑时,电脑可能会出现一些特殊的情况,比如电脑中出现关于dinput8.dll丢失会找不到的情况,出现这样的情况可能会不知道该怎么办,但是出现这样的情况其实并不是一件很难解决的事情,修复dinput8.dll丢失方法也是比…

MySQL InnoDB 引擎底层解析(二)

6.2.InnoDB 的表空间 表空间是一个抽象的概念,对于系统表空间来说,对应着文件系统中一个或多个实际文件;对于每个独立表空间来说,对应着文件系统中一个名为表名.ibd 的实际文件。大家可以把表空间想象成被切分为许许多多个页的池…

关于Unity Time.deltaTime的理解和使用

Unity中的Time.deltaTime是一个表示上一帧到当前帧所用时间的浮点数。 它可以让Unity应用程序能够以平滑的方式在不同的帧率下运行。 要深刻理解Time.deltaTime,首先得了解Unity引擎得工作原理。 Unity引擎以每秒帧数(FPS)的形式运行。 比…

Shell判断:模式匹配:case(二)

简单的JumpServer 1、需求:工作中,我们需要管理N多个服务器。那么访问服务器就是一件繁琐的事情。通过shell编程,编写跳板程序。当我们需要访问服务器时,看一眼服务器列表名,按一下数字,就登录成功了。 2、…

JAVA毕业设计111—基于Java+Springboot+Vue的养老院管理系统(源码+数据库+12000字论文)

基于JavaSpringbootVue的养老院管理系统(源码数据库12000字论文)111 一、系统介绍 本系统前后端分离,本系统分为销售、人事、服务、餐饮、财务、超级管理员六种角色 系统主要功能如下: 首页统计:包括今日新增咨询、今日新增预定、今日新增…

树与二叉树堆:堆

堆的概念: 一般是把数组的数据在逻辑结构上看成一颗完全二叉树,如下图所示。 注意:别将C语言中的堆和数据结构的堆混为一谈,本文所讲的数据结构的堆是一种完全二叉树,而C语言中的堆其实是一种内存区域的划分 堆的分类…

【发明专利】天洑软件再度收获六项国家发明专利授权

近日,南京天洑软件有限公司再度收获行业内六项国家发明专利授权,专利名称为:一种发电机绕组温度预警方法及装置(专利号:ZL 2022 1 1525605.3),一种CSTR系统的控制方法及装置(专利号&…