InnoDB存储引擎【MySQL从放弃到入门】

server/2024/12/26 13:44:15/

文章目录

  • InnoDB存储引擎【MySQL从放弃到入门】
    • 1.逻辑架构
      • 1.1 一条SQL语句是怎么执行的呢?
      • 1.2 MySQL存储引擎有哪些?
    • 2.MySQL一行记录是怎么存储的?
      • 2.1 NULL值是如何存储的?
    • 3.char和varchar的区别?
    • 4.数据页
    • 4.1 聚簇索引和非聚簇索引
    • 4.2 Buffer Pool
      • 4.2.1 什么是Buffer Pool?
        • 4.2.2 空闲页?
        • 4.2.3 脏页?
        • 4.2.4 缓存命中率咋样?脏页更新到磁盘时机呢?
          • 1.预读失效
          • 2.Buffer Pool污染
          • 3.脏页更新时机
        • 4.2.5 Buffer Pool可以代替Redis吗?
    • 4.3 Change Buffer

InnoDB存储引擎【MySQL从放弃到入门】

1.逻辑架构

1.1 一条SQL语句是怎么执行的呢?

[图片]

首先,MySQL的连接器会负责建立连接、校验用户身份、接收客户端的SQL语句;之后MySQL会在查询缓存中查找数据,但是在8.0版本移除了;其次MySQL的解析器会对SQL语句进行词法分析和语法分析,然后构建语法树,方便后续模块读取表名、字段、语句类型;然后MySQL的优化器会基于查询成本的考虑,判断每个索引的执行成本,从中选择成本最小的执行计划;最后MySQL的执行器执行查询语句,从存储引擎读取记录,返回个客户端。

1.2 MySQL存储引擎有哪些?

我所了解的存储引擎有InnoDB、MyIsam、Memory。

(ps:那你知道MyIsam和InnoDB有什么区别吗?)

InnoDB在数据存储方面采用的是索引组织表,表数据和索引数据都存到同一个文件中(.frm&.ibd)。MyIsam采用的是堆表,数据和索引分开存储,因此表数据和索引数据会分开放在两个不同的文件中存储。

InnoDB引擎B+树叶子节点存储的是索引和数据,但是MyIsam存储的是索引和数据地址。另外,InnoDB支持行级锁和事务,但是MyIsam都不支持,只支持表级锁。

2.MySQL一行记录是怎么存储的?

表空间由段、区、页、行组成。

[图片]

2.1 NULL值是如何存储的?

[图片]

MySQL存储一行数据的时候,会使用上面这个格式进行存储,其中NULL值列表就是用来保存NULL值的。

MySQL行格式中会用NULL值列表来标记值为NULL的列,每个列对应一个二进制位,如果列的值为NULL,就标记这个位为1,否则为0,所以NULL值不会存储在行格式中的真实数据部分。

NULL列表最少会占用1字节空间,当表中所有列都定义为NOT NULL时,行格式中就不再需要NULL值列表,可以节省1字节空间。

总结,为什么说使用NULL值列表了,就可以节省空间?

就比如,一个字段varchar(200),但是是NULL,如果你不用标记位1来表示它为空,那么会给它分配最多200字节的空间,如果使用NULL列表,只需要1bit就可以表示它是NULL了,就不需要分配这个空间。

3.char和varchar的区别?

假如说一个字段是varchar(10),但它其实只有6个字节,那他内存中占的存储空间是多少?在文件中占的存储空间是多少?

答:内存会占用10字节,文件存储占6字节,并且额外用1-2字节存储可变长字符串长度的空间。(保存达到文件的时候,只会存储实际使用的字符串大小,但是内存会按varchar最大值固定分配大小。)
char是固定长度的字符串类型,它在系统中占用固定的存储空间,如果实际存储的字符串小于定义的长度,系统会自动用空格填充。

varchar是可变长的字符串类型,实际存储只占用实际字符串长度的空间,不会进行空格填充。

4.数据页

4.1 聚簇索引和非聚簇索引

聚簇索引和非聚簇索引的B+树有什么区别?

[图片]

聚簇索引和非聚簇索引最主要的区别就是B+树叶子节点存放的内容不同:

  • 聚簇索引的B+树的叶子节点存放的是主键值和完整的记录;
  • 非聚簇索引的B+树叶子节点存放的是索引值和主键值。

如果查询条件用到了二级索引,但是查询的数据不是主键值,也不是二级索引值,这时在二级索引找到主键值后,就需要回表才能查找到数据,需要扫描两次B+树。如果查询的是主键值,因为在二级索引就能查询到,但时候就会用到覆盖索引,不需要回表,只需要扫描一次B+树。

4.2 Buffer Pool

InnoDB对LRU做了哪些优化?

4.2.1 什么是Buffer Pool?

Buffer Pool就是MySQL为了提高查询性能的一个缓冲池,位于存储引擎层。默认innodb_buffer_pool_size=128MB。

InnoDB会为Buffer Pool申请一片连续的内存空间,然后按照默认的16kb的大小划分出一个个页,Buffer Pool中的页叫做缓存页。

[图片]

为了管理这些缓存页,InnoDB为每一个缓存都创建了一个控制块,这些控制块包括【缓存页的表空间、页号、缓存页地址、链表节点】等。

[图片]

4.2.2 空闲页?

Buffer Pool是一片连续的内存空间,但是在MySQL运行一段时间后,肯定有空闲的也有被使用的。那么这些空闲页怎么办?
我们下次读取磁盘数据的时候,是要遍历Buffer Pool找到一个空闲页吗?那也太浪费的吧。所以就为这些空闲页创建一个Free链表。

那么每当需要加载数据的时候,直接在Free链表拿一个就行。

4.2.3 脏页?

如果说我的缓存页被修改了,那么就直接更新我的磁盘吗?那也太拉低性能了吧。所以就设计了脏页,由后台线程去更新到磁盘好了。

那么怎么找这个脏页呢?那就创建一个链表吧,就叫Flush链表。

4.2.4 缓存命中率咋样?脏页更新到磁盘时机呢?

对于这个Buffer Pool来讲,我们当然希望访问次数多的一直留下,访问次数少的就给他移除。

那么就使用LRU算法,来实现这个功能,具体LRU是什么呢,可以看这篇文章。
https://blog.csdn.net/m0_73337964/article/details/144726361?spm=1001.2014.3001.5501

如果直接使用LRU算法的话,会出现两种问题预读失效和Buffer Pool污染。

1.预读失效

预读失效就是MySQL在访问数据时,会顺带给邻居也读出来,但是这些被提前读出来的邻居,并没有被访问,相当于这个预读白做了,这就是预读失效。

要避免预读失效带来的影响,最好就是让预读的页停留在Buffer Pool里的时间尽可能短,让真正被访问的页移动到LRU链表头部,从而保证真正的热数据留在Buffer Pool里的时间尽可能长。

MySQL将LRU链表分为了两个部分young和old区域。
[图片]

预读的页加载到old区域头部,当页真正被访问时,才将其加入到young区域头部。

2.Buffer Pool污染

当某一个SQL语句,在Buffer Pool比较有限的情况下,可能会将Buffer Pool里的所有页都替换出去,导致大量热数据被淘汰了,等这些热数据又被再次访问的时候,由于缓存未命中,就会产生大量的IO,这就是Buffer Pool污染。

MySQL的解决方案是,进入到young区域条件增加了一个停留在old区域的时间判断。

  • 如果后续的访问时间与第一次访问的时间在某个时间间隔内,那么该缓存页就不会被从old区域移动到young区域的头部。
  • 如果后续的访问时间与第一次访问的时间不再某个时间间隔内,那么该缓存页移动到young区域的头部。
    间隔时间默认为innodb_old_blocks_time=1000ms,也就是说只有同时满足被访问与在old区域停留时间超过1秒两个条件,才会被插入到young区域头部。
3.脏页更新时机
  1. 当redo log日志满了的情况下,会主动触发脏页刷新到磁盘;
  2. Buffer Pool空间不足时,需要将一部分数据页淘汰掉,如果淘汰的是脏页,就先将脏页同步到磁盘;
  3. 空闲时,后台线程定期将适量的脏页刷入到磁盘;
  4. 关闭前,把所有脏页刷入到磁盘。
4.2.5 Buffer Pool可以代替Redis吗?

我觉得不能代替。

4.3 Change Buffer

推荐链接:09 普通索引和唯一索引,应该怎么选择?

原文章来自:揭开 Buffer Pool 的面纱

以上是我的阅读总结。


http://www.ppmy.cn/server/153330.html

相关文章

《Vue进阶教程》(12)ref的实现详细教程

1 为什么需要ref 由于proxy只能代理引用类型数据(如: 对象, 数组, Set, Map...), 需要一种方式代理普通类型数据(String, Number, Boolean...) 设计ref主要是为了处理普通类型数据, 使普通类型数据也具有响应式 除此之外, 通过reactive代理的对象可能会出现响应丢失的情况. …

阿里巴巴2017实习生笔试题(二)

阿里巴巴2017实习生笔试题(二) 2024/12/25 1.下面哪一个不是动态链接库的优点? B A.共享 B.装载速度快 C.开发模式好 D.减少页面交换 解析 1 静态链接库的优点 (1) 代码装载速度快,执行速度略比动态链接库快;…

网站服务器被攻击了怎么办?

当网站服务器被攻击时,可能会出现各种问题,如服务中断、数据泄露、恶意软件感染等。如果不及时采取措施,可能会给企业带来严重的损失。因此,当网站服务器被攻击时,企业需要采取以下措施来应对: 一、快速定…

MYSQL 架构

MySQL 架构设计灵活,采用模块化的分层架构,分为三大层次:连接层、服务层 和 存储引擎层。这种设计让 MySQL 能够适应不同的使用场景并支持多种存储引擎,以下是对其架构的详细解析: 1. 连接层(Connection La…

Vue3中使用Router进行路由配置(图文详情)

Vue3中使用Router进行路由配置 Vue Router 简介 Vue Router 是 Vue.js 官方的路由管理器,它允许您在单页面应用程序(SPA, Single Page Application)中实现导航和页面切换,而无需重新加载整个页面。通过 Vue Router,您…

undefined reference to `vtable for错误

QT构建报错: D:\code\QGraphicsScaleTest\main.cpp:-1: error: undefined reference to vtable for ResizableSvgViewVS编译报错: 1>main.obj : error LNK2001: 无法解析的外部符号 "public: virtual struct QMetaObject const * __cdecl Resi…

大模型讲师叶梓分享前沿论文:ChatDoctor——基于大模型的医疗聊天机器人

人工智能咨询培训老师叶梓 转载标明出处 人工智能讲师培训咨询老师叶梓分享前沿技术:基于大模型的医疗聊天机器人 大模型在医疗领域的应用仍相对有限,通用领域模型在提供医疗建议时常常出现错误。为了解决这一问题,Li等人提出了一个名为ChatD…

Java全栈项目 - 智能考勤管理系统

项目介绍 智能考勤管理系统是一个基于 Java 全栈技术开发的现代化企业考勤解决方案。该系统采用前后端分离架构,实现了员工考勤、请假管理、统计分析等核心功能,旨在帮助企业提高人力资源管理效率。 技术栈 后端技术 Spring Boot 2.6.xSpring Securi…