深入理解MySQL数据库(Innodb存储引擎)

news2024/10/7 10:14:57

1.B+Tree

什么是B Tree

1)树中每个结点至多有M棵子树(即至多含有m-1个关键字)

2)若根节点不是终端结点,则至少有两颗子树

3)所有的叶子结点都出现在同一层次上,并且不带信息
在这里插入图片描述

什么是B+Tree

  • 一个节点里面可以有多个元素
  • 进行过排序
  • B+树的叶子结点之间是有指针
  • 非叶子结点的数据都冗余了一份在叶子结点(B+树的所有元素都能在叶子结点上找到)
    在这里插入图片描述

MySQL中的B+Tree是如何生成的

B+树相当于B树的升级版,这里叶子结点之间是一个单向指针,在MySQL中的B+树叶子结点之间是一个双向指针

2.Innodb的存储结构

Innodb是通过页式存储来存数据的,每页的大小为16kb
请添加图片描述
可以通过语句看出Innodb的页大小为16384bit,16384/1024=16kb,说明Innodb的页的大小为16kb。
也就说明Innodb从磁盘当中读数据和取数据的最小单位是页,当Innodb想要往磁盘当中存数据时就要在磁盘中开辟一个16kb大小的内存空间

3.Innodb页结构是什么样的

  • 首先创建一个 t1 表 并设定存储引擎为Innodb
  • 然后查看当前t1表中的索引可以看出当前表只有一个主键索引,而且表的类型为B树,是因为B+树也是B树的一种
    请添加图片描述
    接着我们不按顺序插入几条数据
insert into t1 values(4,3,1,1,'d');
insert into t1 values(1,1,1,1,'a');
insert into t1 values(8,8,8,8,'h');
insert into t1 values(2,2,2,2,'b');
insert into t1 values(5,2,3,5,'e');
insert into t1 values(3,3,2,2,'c');
insert into t1 values(7,4,5,5,'g');
insert into t1 values(6,6,4,4,'f');

select * from t1

可以看出虽然没有按照顺序插入数据,但是数据还是进行了排序,原因是Innodb底层是B+树结构,所以数据按照B+树进行了自动排序
请添加图片描述

来看看普通查询是如何执行的

如果我们执行select * from t1 where a=7 这条语句按照正常逻辑应该是这样的:
每进拿一行数据就要调用CPU将数据从磁盘中将数据拿到内存中,进行一次磁盘IO。
请添加图片描述
如图可以看出一共8条语句要进行7次磁盘IO才能拿到想要的数据,这样的执行效率非常低。

但是如果存储引擎是Innodb插入和查询是如何执行

因为Innodb的存储结构是页式存储,所以它只需要进行一次磁盘IO,从磁盘中取出一页的数据也就是16kb的数据在内存中。然后再从内存中去操作查询a=7的数据,这样速度就快很多。

Innodb的页结构图大概如下:
请添加图片描述

Innodb插入是如何执行的

Innodb插入数据:

当Innodb插入第一条数据的时候也就相当于没有页,所以就需要新开辟一页,再将数据插入到用户数据区域,效果如图:
请添加图片描述
当插入第二条数据的时候Innodb是会自动根据字段的主键进行排序的,也正是因为这样所以很多时候都建议用主键自 增方式插入主键,这样Innodb就只会直接在后面插入,而不用重新排序。

插入第二条数据:
请添加图片描述

Innodb查询是如何执行的

Innodb执行查询语句
示例图如下:
请添加图片描述
但是如果我们去查询a=30000: select * from t1 where a=30000

我们去遍历整个数据链表时就需要一次遍历所有数据直到找到a=30000,这样的话遍历效率就非常的低,这页是链表的一个缺点,查询效率慢。

Innodb对于这一个问题也有一个非常好的解决办法,那就是页目录,图实例如下:
我们页目录中存放一个当前目录的第一条数据的主键和指针
请添加图片描述
如果一页数据已经存满16kb那么就会新开一页,结构如下:
请添加图片描述
假如我们现在要查询a=6这条数据,数据库会怎么去执行?

因为数据库根本不知道a=6这条数据到底在第几页,所以它就会从磁盘中先取出第一页,然后再也目录中查看页目录为3的所有数据发现没有,然后再通过next指针查找第二页,在第二页的页目录为5里面查找a=6这条数据,如果这样的话,我们有很多很多页的数据,而且数据在最后一页的话,就需要从磁盘中一页一页去取,这样效率也是非常的低。
Innodb是这样处理的:
请添加图片描述
对于上面这种问题Innodb会重新开辟一个页,用来存储每页的页目录的最小的主键值和指针,这样我们只需要从新开辟的这一页中去查看我们的数据具体会在哪一页。大大提高了查询效率

4.主键索引生成的B+树

我们根据这种结构优化一下就能得到Innodb的主键索引生成的B+树的结构,如图:

请添加图片描述

如果我们通过主键索引a字段去查找a=6这数据,就会走索引,执行路线为:

请添加图片描述
这样执行查询语句的效率就非常的高

5.什么是全表扫描

如果不根据主键索引查找:select * from t1 where b=6:

那么这样就没法走索引了,就只能从第一页开始进行查询知道查找到b=6这条数据,这样的过程叫做全表扫描

6.什么是索引页、数据页、聚簇索引(聚集索引)

请添加图片描述
上面的叫做索引页,下面叫做数据页,整个叫做聚簇索引(聚集索引),在Innodb里面主键索引就是做聚簇索引

7.Innodb如何支持范围查找走索引的?

上面我们说了使用select * from t1 where a=6这条语句能够走主键索引

那么如果使用select * from t1 where a > 6能不能走索引呢?用代码实现看看

请添加图片描述

它的底层是先利用索引找到a=6这条数据,然后返回a=6后面的所有数据,所以它还是走了索引。

8.为什么要遵守最左前缀原则才能利用到索引?

创建主键索引Innodb会根据主键进行排序,那么创建bcd索引Innodb也会根据bcd进行排序,首先按照b排序,如果b字段一样大就会看c字段谁小谁就在前面,依次类推再看d字段。

首先创建一个联合bcd索引,那么bcd索引生成的B+树结构按照惯例应该是下面这样:

请添加图片描述

但是如果bcd索引的B+树结构是上述这样的话会出现一个问题,那就是如果执行更新数据的操作后,所有的索引的叶子结点都需要去修改,这样既浪费了空间,有存了一些没有必要的字段。

那么进行优化后的结构就位最终的bcd索引的B+树:

请添加图片描述

经过优化后如果我们要执行查找select * from t1 where b=1 and c=1 and d=1就可以根据bcd索引找到相应的主键值,然后再通过主键索引回表查询到相应的数据

通过拿到主键值,再通过主键索引查找对应数据这样的操作叫做回表

  • 如果我们执行select * from t1 where c=1 and d=1 and b=1 那么这条语句会走bcd索引吗?

请添加图片描述

由此可以得出一个结论走不走bcd索引跟它的条件字段的顺序是没有关系的,只要条件里面包含了bcd字段就能走bcd索引。

  • 那如果执行select * from t1 where c=1 and d=1 条件里没有了b字段看看会不会走bcd索引?

请添加图片描述

原因:如果是上面的语句可以从条件看出条件是这样的 ? 1 1 b是没有值,c=1 d=1,所以没有满足最左前缀原则,就不会走bcd索引。

  • 再看看执行select * from t1 where b=1 and d=1

请添加图片描述

原因:条件是这样的1 ? 1,只有中间c没有值,a=1,d=1,满足了最左前缀原则

  • 再看看执行select * from t1 where b=1

请添加图片描述

综合上面几种情况就能弄清楚什么是最左前缀原则

9.范围查找导致索引失效原理分析

执行范围查找有时候会导致索引失效的原因是什么?

执行一条语句: select * from t1 where b>1

请添加图片描述

如果执行 select * from t1 where b>6

那么就只会进行一次回表操作,所以这条语句就会走索引

总结:范围查找的范围越精确才不容易导致索引失效

10.覆盖索引的底层原理

执行 select b from t1 where b>6

请添加图片描述

我们通过条件b>1查找b字段,走索引只能查找到所有不完整的字段,而恰巧这些不完整的字段当中含有b字段,那么我们就不需要进行回表查询,直接将b字段返回,这种就叫做覆盖索引。

11.order by为什么会导致索引失效

执行SELECT * FROM t1 ORDER BY b,c,d

请添加图片描述

为什么会导致不走索引而是全表扫描呢?

虽然走索引的话不需要额外排序,因为我们是查找表中所有数据,Select * 所以我们每找到一条数据就要通过数据的主键值进行回表操作,所以在这里需要进行8次回表操作,而如果进行全表扫描的话就只要需要将所有的数据读取到内存中,然后再内存中进行排序,内存的速度是非常快的所以效率要比走索引高得多。

12.MySQL中数据类型转换

MySQL自动会将varchar类型的字母转换成0

比如: 'a'=0返回的是1,true。 'a'=1返回的是0,false。会将字符串中的数字转成对应的数字: '123'=123

13.为什么对字段进行操作后会导致索引失效

如:SELECT * FROM t1 WHERE b+1=1-1

对b字段进行了+1的操作就会导致索引的B+树结构破坏。

因为如果一旦对字段进行了操作后就会破坏原有的B+树的结构,所以对字段进行操作后是不会走索引的。

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

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

相关文章

【毕业设计】37-基于单片机智能楼宇消防监控系统设计(原理图工程+仿真工程+源代码+答辩论文+答辩PPT)

【毕业设计】37-基于单片机智能楼宇消防监控系统设计(原理图工程仿真工程源代码答辩论文答辩PPT) 文章目录【毕业设计】37-基于单片机智能楼宇消防监控系统设计(原理图工程仿真工程源代码答辩论文答辩PPT)资料下载链接任务书设计说…

Redis集群(Cluster)

Redis集群(Cluster) 单台redis容量限制,如何进行扩容?继续加内存、加硬件么?单台redis并发写量太大有性能瓶颈,如何解决?redis3.0中提供了集群可以解决这些问题。 redis集群是对redis的水平扩容,即启动N个…

静态后台管理(9页)

⛵ 源码获取 文末联系 ✈ Web前端开发技术 描述 网页设计题材,DIVCSS 布局制作,HTMLCSS网页设计期末课程大作业 |学生管理系统网页设计 | OA管理系统 | 后台管理模板 | 智能停车系统 | 等网站的设计与制作 | HTML期末大学生网页设计作业,Web大学生网页 H…

C++ Visual Studio 2022 中的改进、行为更改和错误修复

目录 Visual Studio 2022 版本 17.4 中的一致性改进 作用域的基础类型没有固定类型enum 定义中没有固定基础类型的枚举器类型enum Visual Studio 2022 版本 17.3 中的一致性改进 改进了指针之间的修饰符兼容性检查 Visual Studio 2022 版本 17.2 中的一致性改进 未终止的双向…

【分隔结构】定从分离

形式 先行词 其他定语 定语从句先行词 状语 定语从句作主语的先行词 谓语 定语从句 练习一 他们从一部分人来说,是受到了 1998 年才获得的 DNA 证据的启发,这份 DNA 证据,几乎肯定的证明了 Thomas Jefferson 和 他的奴隶 Sally Hemin…

力扣(LeetCode)16. 最接近的三数之和(C++)

双指针 快排使 numsnumsnums 正序。 设置三个指针 iii 指向 numsnumsnums 第一个数,从前往后枚举 nums[i]nums[i]nums[i] , lll 从 nums[i1]nums[i1]nums[i1] 往后,指向第二个数,rrr 从 nums.size()−1nums.size()-1nums.size()…

【博客539】使用openssl手动为k8s集群签发证书

使用openssl手动为k8s集群签发证书 创建ca私钥和ca证书 1、生成ca私钥:生成一个 2048 位的 ca.key 文件 openssl genrsa -out ca.key 2048 2、基于ca私钥,生成根(root)证书:在 ca.key 文件的基础上,生成 ca.crt 文件 openssl re…

[MQ] 交换机与队列的介绍

✨✨个人主页:沫洺的主页 📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏 📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专…

[Spring Cloud] Open Feign 使用

✨✨个人主页:沫洺的主页 📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏 📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专…

机械设计基础试题3

一、判断题(请在后面的括号中,正确的填√,错误的填) (20分) 1. 如果机构的自由度F=2,则机构无确定性运动。 ( ) 2. 作相对运动的三个构件的三个瞬心不一定在一…

JavaEE 进阶:Spring 的创建和使用

文章目录前言一、创建 Spring 项⽬1、创建⼀个 Maven 项⽬2、添加 Spring 框架⽀持3、添加启动类二、存储 Bean 对象1、创建 Bean2、将 Bean 注册到容器三、获取并使⽤ Bean 对象1、创建 Spring 上下⽂① ApplicationContextⅠ 注意事项② BeanFactory③ ApplicationContext VS…

【浅学Java】Bean的作用域和生命周期

Bean的作用域和生命周期1. Bean的作用域1.1 什么是Bean的作用域1.2 Bean的6种作用域singleton——单例作用域prototype——多例作用域request——请求作用域session——会话作用域application——全局作用域(了解)websoccket——HTTP WebSocket作用域(了解)1.3 设置作用域2. Be…

计算机毕业设计node.js+vue+Element企业员工信息管理系统

项目介绍 随着Internet的发展,人们的日常生活已经离不开网络。未来人们的生活与工作将变得越来越数字化、网络化和电子化。本文以实际运用为开发背景,运用软件工程原理和开发方法,它主要是采用node框架和node来完成对系统的设计。整个开发过程首先对企业员工管理系统进行需求分…

LVS-NAT模式部署

目录 一、环境准备 1、准备三台centos服务器 2、实验拓扑 3、NAT模式介绍 二、LVS-NAT模式部署 1、给lvs服务器安装LVS 2、新建LVS集群 3、添加Real Server服务器节点 4、开启路由转发 5、给后端web服务器配置网关 6、效果测试 一、环境准备 1、准备三台centos服务器…

ctfhub-web-warmup

打开题目链接 是一张图 查看源代码 提示source.php 访问这个文件 得到源码 <?phphighlight_file(__FILE__);class emmm{public static function checkFile(&$page){$whitelist ["source">"source.php","hint">"hint.php…

Java毕业设计项目_企业级实战全栈项目中信CRM

【教程、代码】文章底部 1.学习目标视频教程目录【教程、代码】文章底部2.CRM 系统概念与项目开发流程2.1. CRM基本概念 圈内存在这么一句话&#xff1a;“世上本来没有CRM&#xff0c;大家的生意越来越难做了&#xff0c;才有了CRM。”在同质化竞争时代&#xff0c;顾客资产尤…

[附源码]java毕业设计社区医院管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

RabbitMQ初步到精通-第六章-RabbitMQ之死信队列

目录 第六章-RabbitMQ之死信队列 1. 死信概念 2. 死信架构 3. 死信来源 3.1 消息 TTL 过期 3.2 队列达到最大长度&#xff08;队列满了&#xff0c;无法再添加数据到 mq 中&#xff09; 3.3 消息被拒绝&#xff08;basic.reject 或 basic.nack&#xff09;并且 requeuefa…

基于stm32单片机的智能恒温箱游泳池

资料编号&#xff1a;104 下面是相关功能视频演示&#xff1a; 104-基于stm32单片机的智能恒温箱游泳池控制系统Proteus仿真&#xff08;源码仿真全套资料&#xff09;功能介绍&#xff1a; 采用stm32单片机&#xff0c;程序可以设置最高值和最低值&#xff0c;当温度超过最高…

[笔记]vue从入门到入坟《五》vue-cli构建vue webpack项目

参考&#xff1a; 用vue-cli搭建vue项目 vue-cli 项目结构目录简介 文章目录前言一、Vue-cli介绍二、开始2.0 下载安装npm 以及gitnpm安装git安装2.1 全局安装 vue-cli2.2 创建项目目录介绍三、常见问题总结前言 一、Vue-cli介绍 官网 简单地说就是构建vue项目的工具包&#…