【从删库到跑路 | MySQL总结篇】索引的详细使用

个人主页:兜里有颗棉花糖
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创
收录于专栏【MySQL学习专栏】🎈
本专栏旨在分享学习MySQL的一点学习心得,欢迎大家在评论区讨论💌
在这里插入图片描述

目录

  • 一、索引
    • 索引介绍
    • MySQL中索引的使用
      • 查看索引
      • 创建索引(危险危险)
      • 删除索引(比较危险)
  • 二、索引底层数据结构
    • B-树
    • B+树
  • 三、索引总结

一、索引

索引介绍

索引就相当于一本书的目录(index),比如我们如果想要快速查找到书中的某一部分内容,我们就可以查看索引来找到我们指定的内容。

而在MySQL中,表中存储的数据是非常庞大的,最基本的方式就是把表中的数据进行一条一条的进行遍历,但是这样的遍历方式的速度太慢了,因为数据库中的信息量是非常庞大的。所以,我们就需要给数据库中的表建立一个索引(建立索引的方式是按照列的维度进行建立的)来提高我们的查找速度。

我们不妨来举个例子,请看下面这张表:在这里插入图片描述
我们首先要知道,一张表中一般是存在很多列的,而针对列的不同,查询的方式也是会有所区别的。比如上面这张表,有时候是按照id进行查询的,有时候是按照name来进行查询的,也有时候是按照qq_email来进行查询的等等
假设我们现在来按照id来进行查询,此时在数据库中就会开辟出额外的一块空间来维护和id相关的信息(这里是通过特定的数据结构来维护表示id相关索引的情况):
如id 为 1 => 对应表中的某个数据
如id 为 2 => 对应表中的某个数据;
如果后续再来按照id进行查询的时候,此时就不需要一条一条遍历数据了。而是从索引中直接进行查询,根据索引就能够初步锁定数据所在的位置

现在有这么一种情况:如果我们是按照id来建立索引的话,而后面是按照name来进行查询的,此时是不能提高效率的;如果想要name加快查找的话,我们可以给name建立索引,

我们现在已经知道索引是用来提高查询速度的。
但是查询速度的提高是要付出一定的代价的:即要消耗额外的空间(主要是硬盘空间)。如果我们想要向表中添加数据的话,此时我们还要修改索引;如果我们要修改或者删除的数据涉及到索引列的删除或者修改,此时我们依然是需要维护索引的。

MySQL中索引的使用

查看索引

查看索引
语法格式:show index from table_name;

举个栗子1:
输入命令:create table student(id int primary key,name varchar(20));
查看当前表的结果,如下图:
在这里插入图片描述
我们可以看到上表中存在主键id,mysql中当表中存在主键的时候系统就会自动地给这个列来创建索引;同时由于主键是不允许重复的,因此要想插入或者修改数据的话,就需要先进行查询,来看看插入或者删除后的结果是否存在。
举个栗子2:
输入命令:create table student(id int unique,name varchar(20));show index from student;
查询结果如下:
在这里插入图片描述
可以看到上述中,如果使用unique约束的话也会自动生成索引。

举个栗子3测试数据的sql语句:
create table classes(classes_Id int primary key,name varchar(20));
create table student(id int primary key,name varchar(20),classes_Id int,foreign key (classes_Id) references classes(classes_Id));

// 查看索引
show index from classes;
show index from student;

举个栗子3:
查询结果如下:
在这里插入图片描述
其中classes表和student表中各有一个主键约束自动创建的索引,同时student表中存在一个外键约束自动创建的索引。

如上图,外键约束也是会自动生成索引的;当然,外键约束也是会涉及到自动查询的。这里我们来举两个栗子,在这之前,我们再来回顾一下下面需要用到的student表classes表,请看:
在这里插入图片描述
现在来进行外键约束也是会涉及到自动查询的的举例。
举个栗子1:当我们需要在学生表中插入数据的时候就需要查询classes_Idclasses表中是否存在,此处的查询就需要用到classes表classes_Id(即classes表中主键自动申城的索引)
举个栗子2:当我们想要删除classes表中的一条记录,我们就需要需要查询classes表中的classes_Id是否在student表中存在。如果存在的话,此时就是删除失败(删除失败原因就是子表对父表的反向约束作用)。而此处的查询就用到了student表中的classes这一列对应的索引(此索引就是外键约束自动生成的)

上述三种情况:主键unique外键都会使表自动创建出索引。所以此时我们就不需要再对单独的这一列创建单独的索引了。

创建索引(危险危险)

手动给指定的列创建索引语法格式:create index 索引名 on 表名(字段名);

这里依然使用上述的两张表(student表classes表),请看:
在这里插入图片描述
下面我们来简单的创建索引:
输入命令:create index idx_student_name on student(name);
创建索引结果如下:

在这里插入图片描述
我们来查看一下我们刚刚创建的索引,输入命令:show index from student;
在这里插入图片描述
如上图我们可以观察到我们刚刚新创建出来的索引(在上图中的最后一行)。

然而这里我们不得不提到:创建索引的操作是非常危险的。(真是的,怎么我写个sql语句就这么困难呢?到处都是危险操作)
如果我们创建的索引所在的表的数据是空的或者表中的数据本身就不多,此时我们创建索引的操作就不是危险操作
但是,如果表是非空的,并且表中的数据量是非常庞大的,那么此时如果我们创建索引的话就会引起非常庞大的硬盘IO操作。甚至会消耗大量的cpu资源,从而进一步导致数据库被卡死。
所以我们创建表的时候一定要想好到底要不要创建索引,提前考虑好表的结构中的哪一列需要创建索引,因为后期一旦我们再想创建索引的话就有点不切实际了,所以凡事要趁早,提前做好规划。

删除索引(比较危险)

删除索引只能删除手动创建的索引。

删除索引语法格式(指定要删除的索引名和表名即可):drop index 索引名 on 表名;
还是来举个栗子,现在我们要删除刚刚给student表中的name创建的索引,如果你忘记了刚刚student表结构,那么请看下图来回忆以下:
在这里插入图片描述
输入命令: drop index idx_student_name on student;
结果如下(检验是否删除索引成功),请看下图:
在这里插入图片描述
可以看到我们刚刚创建的idx_student_name索引删除成功了。

上面我们提到过只能删除手动创建的索引,我们试试能不能删除student表自动创建的索引classesId,输入命令:drop index classes_Id on student;结果如下:
在这里插入图片描述
报错原因:外键约束需要索引classes_Id
由此我们可以看出我们只能删除手动创建的索引,而自动创建的索引是不能被删除的。

删除索引这个操作也是比较危险的,不能轻易删除索引。

假设有这样一个场景:现在我们有一个有很多很多数据的表,同时这个数据库此时是处于生产环境的一个数据库。但是我们现在必须要创建删除索引。此时怎么办呢?我们要知道数据库服务器往往不仅仅是单台服务器,为了整个系统的稳定性,通常会搞出多个mysql服务节点,这些节点的数据往往都是一样的,能够提出相同的服务。以防万一某个mysql服务器节点挂了,而其它服务器依然可以很正常运行

此时我们可以这样做:先准备好一个新的mysql服务器,把表和索引都创建好,然后把数据都导过来,再把要替换的mysql服务器关闭掉,然后再把新的mysql服务器替换掉就好了。

二、索引底层数据结构

MySQL底层的数据结构并不是一个定式,而是取决于MySQL使用哪个存储引擎

那什么又是存储引擎呢?
MySQL这个程序中包含了许多模块:有的模块是负责解析sql的;有的模块是负责网络通信的;而有的模块则是用来存储数据的。我们用来存储数据的相关的模块称为存储引擎(本质上就是代码中的一个模块,这个模块中包含了若干个代码文件以及一堆具体的代码)。
而具体如何来进行数据的存储,MySQL支持多种存储方案。Innodb是当下最主流的一种存储方案。
数据库中组织数据所使用的数据结构是在硬盘上的。(这里就与内存中的数据结构就有所区别了)

内存上的数据结构(比如我们平常实现的链表、二叉树、顺序表等都是存储在代码内存中的)对于访问操作来是是非常不敏感的。(其实内存中的数据结构进行访问所占用的时间并不多,真正占用时间的而是找数据的过程
硬盘上的数据结构对于访问操作来说是比较敏感的,读写一次硬盘的开销是远远大于内存的,此时我们就不得不考虑访问所带来的开销了且读写一次硬盘相当于读写约10000次内存。

好了,我们现在来看看索引到底是使用哪种数据结构比较合适吧!在这之前我们首先要明白索引是用来干什么的,嗯对,索引的目的其实就是方便我们进行快速的查找。回顾我们以往学到的数据结果中,能够做到快速查找的一个是二叉搜索树(带有平衡机制的二叉搜索树),另外一个就是哈希表了。
但是哈希表并不适合作为索引的底层结构,因为哈希表(哈希表基本执行过程就是把给定的key通过hash函数映射出一个具体的下标才能定位到具体位置)无法做到范围查询或者说模糊查询,哈希表只能完成精确查询的任务。

那红黑树其实也不适合作为索引的数据结构,虽然红黑数种的元素是有序的,可以进行范围查询,但是之所以红黑树不能作为索引的数据结构最大的问题就是红黑树的高度(当元素比较多的时候,树就会变的非常高、或者非常深),而树的深度越深比较的次数就越多。而索引这样的数据结构是存储在硬盘上的,每次比较都意味着硬盘IO操作(读写一次硬盘就相当于约10000次内存读写)。所以红黑树不适合作为索引的底层数据结构

在MySQL中的Innodb存储引擎中,索引的底层数据结构是B+树;而在其它存储引擎中,也可能会用到hash索引,此时就只能应对精准匹配查询的这种情况(所以hash并不是不能作为索引,只是丧失了部分功能而已)。

想要清楚什么是B+树,我们就需要先知道什么是B - 树

B-树

B - 树(本质是N叉搜索树B 树的一个节点上可以保存多个keyN个key就可以延伸出N+1个分支。查找元素的流程就是拿着要查找的元素从根节点出发(判断要查找的元素是否在根节点上),如果不存在的话,我们就需要看看这个元素最终落到哪个区间内,然后沿着这个区间的路线继续往后找,如果最终的叶子节点依然不存在我们要查找的元素,那么这个要查找的元素就真的不存在了。

在这里插入图片描述

与二叉搜索树相比,B - 树的每个节点可以存储多个元素,在元素总个数相同的情况下,B - 树的节点数和高度都会大大降低;同时B - 树在同一个层次中会存在多个分叉,这也会降低节点数和树的高度。

对于数据库来说,每个节点上的数据都需要从数据库中读取出来才能进行比较(每个节点访问的时候都会进行硬盘的IO操作。)随着B树的节点减少的同时,节点的访问次数就会减少,硬盘IO操作也当然会随之减少。还有一点我们需要知道:一个节点中有一个key和一个节点中有多个key的节点访问时的硬盘IO操作的开销是差不多的。

B树的插入元素和删除元素会涉及到拆分合并的操作,解释如下:
B树中的一个节点的确可以保存多个key,但是也不可以无限的进行存储,当key的数量到达一定程度的时候,此时就需要把这个节点进行拆分,即把这个节点中的一部分key以树的子节点的方式进行重新组织,这样就可以保证每个节点中的key的数量不会太多(当然也会衍生出新的叶子几点)。
B树的合并操作:B树的合并操作一般是在节点删除后执行的,因为当删除一个节点时,会导致 B 树的高度降低,可能会破坏 B 树的平衡性,需要对 B 树进行合并操作以保持平衡。
关于B树的拆分和合并操作:具体什么时候进行拆拆分,怎么拆分;什么时候合并,怎么合并需要看具体的实现,同时不同场景下会有不同的应对策略。

B+树

好了,现在我们来了解下数据库中索引的主角:B+树(N叉搜索树)。B+树在B树的基础上又做出了一些改进。

B+树特点:

  • N个key分出了N个区间,每个节点上的最后一个key就是最大值(也可能是第一个key,即最小值)。
  • 父节点中的key会在子节点中重复出现(以最大值或者最小值的身份),这样就会出现一个效果,即叶子节点这一层的的数据包含了整个数据的全集。
  • 把叶子节点进行链表方式的首尾相连,此时叶子节点这样的一个连接方式就可以快速找到上一个或者下一个节点,方便进行范围查询(只要能确定开头和结尾,开头和结尾中间的子链表就是我们查询出来的结果)。

在这里插入图片描述

好了,以上就是本文的全部内容,就到这里吧!!!再见啦友友们~~~

三、索引总结

好了,现在再来重新回顾一下索引吧!!!

索引简单点来说就相当于一本书中的目录,可以加快我们的查找速度。并且索引是按照列来进行查询的。

索引的优劣:

  • 优点提高查询速度。
  • 缺点占据额外的内存空间。一定程度上会拖慢插入修改删除数据的速度。

索引具体的使用方式:

  • 创建索引:会自动创建的索引:主键外键unique。手动创建索引语法格式:create index 索引名称 on 表名(列名);
  • 查看索引:show index from 表名;
  • 删除索引:drop index 索引名 on 表名;

索引的数据结构:

  • hash不适合作为索引的数据结构,原因是因为hash不能够进行范围查询,不能够进行模糊匹配查询。
  • 红黑树也不适合作为索引的数据结构,虽然红黑树可以进行范围查询,但是需要引入更多的硬盘IO操作
  • B+树就非常适合索引的数据结构,在MySQL中的Innodb存储引擎中的索引就是以B+树作为底层数据结构的。

B+树的优势:

  • B+树非常擅长范围查询,即只要找到开头和结尾,那么中间那一部分的链表就是我们要查找的数据。
  • 所以的查询操作的查询时间非常稳定,因为所有的查询操作最终都会落在叶子节点上。而B树的话有点数据可能在根节点找到,有的数据可能在叶子节点找到,这样的话查询速度就很不稳定。(某些时候,稳定比快速更加重要
  • 由于叶子节点上是完整的数据全集,因此表的每一行数据的其它列都可以保存在叶子节点上(我们要知道物理结构中并不存在表格这样的数据结构,所以我们可以使用B+树来存储表中的数据,表格只是看起来像一个表格而已),而非叶子节点只存储构建索引的key即可(ID)。此时非叶子节点的存储空间是非常小的以至于我们可以在内存中缓存一份,这样的话在进行数据查询的时候就可以通过内存来直接进行数据的比较,从而更快速的找到叶子节点上的记录(这里又进一步的减少了硬盘IO操作的次数)。而B树的话由于B树的整个数据的全集并非只有叶子节点,非叶子节点也有可能是数据的全集。
  • B树如果也要把元素存储到每个节点上,非叶子节点所占用的空间就会变大,从而无法在内存中进行缓存了。当然对应的硬盘IO操作也会增多。

在这里插入图片描述
嗯,本文就到这里吧,再见啦友友们!!!
记得一键三连哦!!!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

KMP基础架构

前言 Kotlin可以用来开发全栈, 我们所熟悉的各个端几乎都支持(除了鸿蒙) 而我们要开发好KMP项目需要一个好的基础架构,这样不仅代码更清晰,而且能共享更多的代码 正文 我们可以先将KMP分为前端和服务端 它们两端也能共享一些代码,比如接口声明,bean类,基础工具类等 前端和…

【Linux】TCP套接字编程

目录 前言 UDP服务器的完善 线程的封装 结构定义 接口实现 环形队列 结构定义 接口实现 加锁 信号量的申请与释放 入队与出队 整体组装 初始化与析构 信息接收线程 消息发送线程 TCP套接字 创建套接字 listen accept 收发操作 客户端的编写 进一步完善 …

centos8 在线安装、离线安装cmake

在线安装 yum install -y cmake make 离线安装 通过finalshell 上传离线安装包 离线安装 进入到程序所在路径下执行命令进行安装 rpm -Uvh --force --nodeps *.rpm

单元测试与白盒测试的区别

测试技术: 1. 白盒测试和单元测试的区别: l 单元测试和白盒测试是不同的,虽然单元测试和白盒测试都是关注功能虽然他们都需要代码支持,但是级别不同,白盒测试关注的是类中一个方法的功能是更小的单位,但是完成一个单元测试可能需要N多类,所以说作单元测试需要什么写驱动和稳定…

【SpringBoot系列】SpringBoot时间字段格式化

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

java设计模式学习之【单例模式】

文章目录 引言单例模式简介定义与用途实现方式:饿汉式懒汉式 UML 使用场景优势与劣势单例模式在spring中的应用饿汉式实现懒汉式实现数据库连接示例代码地址 引言 单例模式是一种常用的设计模式,用于确保在一个程序中一个类只有一个实例,并且…

【蓝桥杯选拔赛真题71】Scratch绘制彩虹 少儿编程scratch图形化编程 蓝桥杯创意编程选拔赛真题解析

目录 scratch绘制彩虹 一、题目要求 编程实现 二、案例分析 1、角色分析

C陷阱与缺陷——第8章建议

不要说服自己相信”皇帝的新装“,有些看上去正确的语句实际是有问题的直接了当地表明意图,当你写的代码有可能被误解成其他含义时,可以通过加注释等方式让你的意图更加清晰;有些错误可以做到事先预防 4. 考察最简单的特例&#xf…

修改el-table表头样式

<style lang"scss" scoped> ::v-deep .el-table {.el-table__header-wrapper, .el-table__fixed-header-wrapper {th {word-break: break-word;background-color: #f8f8f9;color: #515a6e;height: 40px;font-size: 13px;}} } </style>

光伏电站卫星测绘的优缺点有哪些?

由于环境保护和能源安全的重要性日益凸显&#xff0c;光伏发电作为一种清洁、可再生、分布式的能源形式&#xff0c;已经成为全球能源领域的热门话题。 光伏电站&#xff0c;是指一种利用太阳光能、采用特殊材料诸如晶硅板、逆变器等电子元件组成的发电体系&#xff0c;与电网相…

电话号码的字母组合(C++实现)

电话号码的字母组合 题目代码思路及代码讲解代码&#xff08;有注释版&#xff09; 题目 电话号码的字母组合 代码 class Solution {const char* numsStrArr[10]{"","","abc","def","ghi","jkl","mno"…

使用调研工具做好问卷调查的方法与策略

提起问卷调查大家应该都不陌生&#xff0c;学校会使用问卷调查收集学生信息或意见、企业使用问卷调查了解市场、深入用户。和其他的调查方式相比&#xff0c;问卷调查更能贴近被调查者真实想法&#xff0c;反馈真实数据。而互联网的崛起也使得大家纷纷从线下问卷转战到线上问卷…

ubantu配置网卡ip

1.ifconfig查看网卡 2. vi /etc/network/interfaces auto ens33 # 网卡名 iface ens33 inet static # 注意网卡名 address 192.168.43.10 # 配置ip地址 netmask 255.255.255.0 # 掩码 gateway 192.168.43.1 # 网关 3.重启网卡 ifconfig ens33 down ifco…

GoLong的学习之路,进阶,微服务之原理,RPC

其实我早就很想写这篇文章了&#xff0c;RPC是一切现代计算机应用中非常重要的思想。也是微服务和分布式的总体设计思想。只能说是非常中要&#xff0c;远的不说&#xff0c;就说进的这个是面试必问的。不管用的上不&#xff0c;但是就是非常重要。 文章目录 RPC的原理本地调用…

【JavaScript】3.4 JavaScript在现代前端开发中的应用

文章目录 1. 用户交互2. 动态内容3. 前端路由4. API 请求总结 JavaScript 是现代前端开发的核心。无论是交互效果&#xff0c;还是复杂的前端应用&#xff0c;JavaScript 都发挥着关键作用。在本章节中&#xff0c;我们将探讨 JavaScript 在现代前端开发中的应用&#xff0c;包…

【PixPin】媲美QQ/Snipaste截图贴图OCR工具

PixPin PixPin是一款截图工具&#xff0c;它集成了截图、长截图、贴图、标注、OCR识别等众多功能&#xff0c;软件体积小巧&#xff0c;使用简单&#xff0c;是一款非常棒的截图工具。之前使用过Snipaste工具的小伙伴用起来应该是得心应手。 从左往右的功能依次是&#xff1a;…

你好!插值查找【JAVA】

1.初次相识 插值查找&#xff08;interpolation search&#xff09;是一种根据待查找关键字在有序数组中的大致位置决定查找范围的查找算法。插值查找与二分查找类似&#xff0c;区别在于插值查找对于待查找关键字在数组中的位置进行估计&#xff0c;从而更精准地定位到待查找关…

数据结构-03-栈

1-栈的结构和特点 先进后出&#xff0c;后进先出 是栈的特点&#xff1b; 从图中&#xff0c;我们看到A入栈先放入底部&#xff0c;然后依次B和C&#xff1b;出栈的顺序依次是C-B-A&#xff1b;这种结构只能在一端操作。所以当某个数据集合只涉及在一端插入和删除数据&#xf…

0-1背包问题详解

0-1背包问题 部分一&#xff1a;问题描述 0-1背包问题是一类经典的组合优化问题&#xff0c;它出现在很多实际生活和工业环境中。问题描述如下&#xff1a; 假设你是一个冒险家&#xff0c;带着一个可承重的背包&#xff0c;面对一堆宝物。每件宝物都有自己的价值&#xff0…

新闻宣传稿怎么写?手把手教你!

一篇高质量的的新闻宣传稿是如何炼成的&#xff1f;本文伯乐网络传媒将带你走进这个神秘的领域&#xff0c;揭秘爆款文案背后的秘密。在这里&#xff0c;你将学到一系列实用技巧&#xff0c;让你的新闻宣传稿更具吸引力、独特见解和深度。 一、选题与立意&#xff1a;抓住热点&…
最新文章