MySQL进阶难度知识点分析

news2024/9/24 7:25:05

        以下为本人在阅读《MySQL是怎样运行的:从根儿上理解MySQL》这本书时对一些难度和重点的笔记,主要用于个人学习使用,内容可能存在出入,望理性食用~

1. sql执行流程

        一条sql的执行流程大致可分为客户端获取与数据库服务器的连接,然后查询缓存(MySQL 8.0之后移除),解析和优化,最后交给存储引擎进行具体数据的读取与写入。

        其中解析是指语法分析、词法分析、语义分析等,解析一条sql语句是否有语法错误,确定其查询的是哪个表,条件是什么,是否有索引等,然后优化器会进行优化,选择最优的执行计划,通过explain可以查看执行计划。

2. MySQL的内存结构

        存储引擎与硬盘的I/O通过中间的内存进行交互,页是内存与磁盘进行交互的基本单位,一个页中包含多干条记录,InnoDB中页的大小一般为16KB。存储引擎中有不同的页,有的页存放表结构,有的页存放Insert Buffer、有的页存放undo日志等,其中存放记录的页称为索引页,也可称为数据页

        16KB的页中包含不同的分区,每个分区有不同的功能,其中存放实际记录的分区称为User Records,未插入数据时为空,当插入数据时会从Free Space(未使用空间)中分一部分空间给User Recods来存放数据,当Free Space为0,仍有数据插入时,则插入到其他页中。

        页中还包含存放表信息的File Headers和存放页信息的Page Headers,具体分区情况如下:

        一条记录中,不仅包含实际的字段数据,还包含其他数据,比如记录的头信息、真实数据中的NULL值情况等,同时还要三个隐藏列:row_idtransaction_idroll_pointer。其中row_id是指当表中没有指定主键且不包含唯一索引时,会自动根据记录的物理存储顺序创建一个row_id用于记录的排序使用,transaction_id是事务id,roll_pointer是回滚指针。

        16KB的页中存储若干条记录项,这些记录根据主键id排序,每条记录之间使用单链表进行连接(next_record字段记录下一条记录的地址偏移量,用于查找下一条记录),为便于查询每条记录,不用每次查询都遍历所有的记录,将所有记录项按块进行分组,每个分组对于一个槽,这些槽(页面目录中的这些地址偏移量被称为)记录了该分组中主键id最大的位置,页中的所有槽构成了页目录,通过二分法查找页目录可以快速定位到所查记录项所在分组,然后通过next_record遍历该槽中的各个记录查找即可,以此来提高查询效率。具体来说,在一个完整的页中,每隔6条数据就会有一个Slot。

        同时记录项中有个delete_mask属性,用于逻辑删除使用,即值为0表示未删除,为1表示已删除,因为没从页中实际删除一条记录,移除该数据后需要从磁盘中重新进行I/O读取数据,效率较低,因此设置逻辑删除属性。

3. 为什么要有索引?

        每个数据页中的记录会按照主键的大小通过单链表进行连接,各个数据页通过双向链表进行连接。因为页的大小有限,一张表的数据量较大时,需要很多页来存储,当没有使用索引的情况下,每次查找一条记录时,只能从头遍历所有的页,来确定该记录存在于哪个页中,然后在页中二分查找来找到对应的记录,时间复杂度很高。

        参照AVL平衡二叉树的查找方式,MySQL的索引使用B+树进行降低查找的时间复杂度。在B+树中,非叶子结点存储了每个页中的最小主键值和页号,通过最小键值可以判断要查找的键值应该存在于哪个页中,通过页号可以直接定位到所要查找的页,使得每次查找只需从根节点比较主键的值,然后依次比较每个结点的键值,最后找到该记录存在于哪个叶子节点中,在该叶子节点中使用二分查找即可。

4. 页之间为什么要用双链表进行连接?

        因为当频繁的插入或删除数据时,页内的数据量会进行变化,当页内存储的数据量太小或者太大导致需要增加新叶或删除当前页时,为保证记录按照主键有序排列,需要进行页分裂,因此需要知道当前页的前后页的位置,故需要使用双向链表进行连接。

5. 回表的缺点

        因为非聚族索引的叶子节点只存放索引的键值和主键的值,不存放具体的数据,因此在使用非聚族索引如二级索引查数据时,会先根据二级索引查到该数据的主键值,然后到聚族索引中根据该主键值找到具体的数据信息,这种二次查表的过程就是回表,回表会导致查询效率降低,需要额外再查一次表。

        其次回表会导致随机IO,索引的叶子节点中的记录项是根据顺序依次排放的,它们在磁盘中的存储是相连的,因此根据查询的索引键值可以集中的将查询结果从磁盘中读取出来,这种读取方式称为顺序IO,效率高。而在回表查询时,每个索引键值对应的主键值是随机分布的,根据主键值再去聚族索引中查找不同的页中的记录项,这种读取方式称为随机IO,导致与磁盘IO次数增大,效率降低。

6. 使用索引的注意事项

  1. 对于联合索引进行查询时,查询条件要满足最左匹配原则。
  2. 用于排序的情况只有同升或同降才能适用索引,一升一降无法使用索引。
  3. 右模糊匹配适用索引,左模糊和全模糊不适用。
  4. 只对查询、排序或分组字段建立索引,而不是根据查询的结果建立索引。
  5. 索引列的类型尽可能的小,页的大小一定,主键值越小存储的记录项就越多。
  6. 为了尽可能少的让聚族索引发生页面分裂和记录移位的情况,建议让主键拥有AUTO_INCREMENT属性。
  7. 使用到索引的搜索条件和没有使用该索引的搜索条件使用OR连接起来后是无法使用该索引的。

7. Buffer Pool缓存区

        通过前面的知识可以知道InnoDB是以页为单位来存储和读取数据的,数据存储在磁盘中,当需要查询页中的某条数据时,会从磁盘中将相应的整页加载到内存当中,然后在内存中对该数据进行读写操作。而操作完成后并不会立即将该页对应的内存空间释放掉,而是将其缓存起来,以便下次查询到相同的数据时直接进行读取,省去了磁盘IO的开销。

        这个用于缓存磁盘中的页的区域被称为Buffer Pool(中文名是缓冲池,它是MySQL向操作系统申请的一片连续的空间,在MySQL服务器启动时进行初始化,默认空间大小为128M同时为了更好的管理Buffer Pool中的缓存页,每个缓存页都有其对应的控制信息这些控制信息包括该页所属的表空间编号、页号、缓存页在Buffer Pool中的地址、链表节点信息等,每个缓存页对应的控制信息占用的内存大小是固定的,将每个页对应的控制信息所占用的一块内存称为控制块,故一个页对应一个控制块,Buffer Pool对应的内存空间如下:

        刚开始时Buffer Pool内不存放任何数据,只是有空闲的一个个控制块和对应的缓存页构成,随着程序的运行不断有磁盘上的页被加载进该内存空间,那如何来确定Buffer Pool中哪些缓存页是空闲的,哪些已经被使用了呢?因此需要使用free链表来进行管理,其记录了所有空间缓存页的情况(将其对应的控制块放入到链表中),刚开始时所有缓存页均空闲,其对应的控制块都在free链表上,每当需要从磁盘中加载一个页到Buffer Pool中,就从free链表中取一个空闲的缓存页对应的控制块,并将其对应的控制块信息填上,然后从free链表中移除该控制块,表示当前缓存页已被使用。

        如果当我们访问页时,该页已经存在Buffer Pool中,如何确定其已存在呢?如何定位它的位置?

        最高效的方式就是在O(1)的时间复杂度内查询到,故可以使用哈希表,通过key快速找到其对应的value,表空间号 + 页号作为key缓存页作为value创建一个哈希表,在需要访问某个页的数据时,先从哈希表中根据表空间号 + 页号看看有没有对应的缓存页,如果有,直接使用该缓存页就好,如果没有,那就从free链表中选一个空闲的缓存页,然后把磁盘中对应的页加载到该缓存页的位置。

        再来考虑,当我们如何修改了Buffer Pool中的缓存页内的数据时,如何将其对应的页同步到更新到磁盘中去,防止出现脏页MySQL使用flush链表来存储脏页,将凡是修改过的缓存页对应的控制块都会作为一个节点加入到一个链表中,待之后的某个时刻同步到磁盘上。

        那么如果当Buffer Pool中的空间满了,依然有数据要从磁盘加载到该空间中该怎么办,一个很好的思路是将最近最少使用的缓存页释放掉,然后放入新的缓存页,因此根据该规则需再创建一个LRU链表,当我们需要访问某个页时,可以这样处理LRU链表

  • 如果该页不在Buffer Pool中,在把该页从磁盘加载到Buffer Pool中的缓存页时,就把该缓存页对应的控制块作为节点塞到LRU链表头部
  • 如果该页已经缓存在Buffer Pool中,则直接把该页对应的控制块移动到LRU链表头部

        也就是说:只要我们使用到某个缓存页,就把该缓存页调整到LRU链表的头部,这样LRU链表尾部就是最近最少使用的缓存页喽~ 所以当Buffer Pool中的空闲缓存页使用完时,到LRU链表的尾部找些缓存页淘汰就OK啦。

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

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

相关文章

使用 Hugging Face Transformers 创建文本生成模型

文本生成是自然语言处理中的一个重要任务,在聊天机器人、自动写作等领域有着广泛的应用。Hugging Face Transformers 是一个流行的 Python 库,它提供了大量预训练的模型以及API来实现各种自然语言处理任务。本文将详细介绍如何使用 Hugging Face Transfo…

Golang | Leetcode Golang题解之第338题比特位计数

题目&#xff1a; 题解&#xff1a; func countBits(n int) []int {bits : make([]int, n1)for i : 1; i < n; i {bits[i] bits[i&(i-1)] 1}return bits }

工业三防平板在数字化工厂建设中的重要趋势

在当今数字化浪潮的冲击下&#xff0c;工厂建设的数字化转型已,成为不可逆转的趋势。而在这一进程中&#xff0c;工业三防平板正逐渐斩露头角&#xff0c;发挥着越来越重要的作用。随着工业4.0理念的不断深入&#xff0c;工厂对于生产效率、质量控制、管理精细化的要求越来越高…

Elasticsearch核心概念:

2.Elasticsearch核心概念: 2.1.Lucene和Elasticsearch的关系: 1.Lucene&#xff1a;最先进、功能最强大的搜索库&#xff0c;直接基于lucene开发&#xff0c;非常复杂&#xff0c;api复杂2.Elasticsearch&#xff1a;基于lucene&#xff0c;封装了许多lucene底层功能&#xf…

2-67 基于matlab的经典数字图像处理算法仿真

基于matlab的经典数字图像处理算法仿真&#xff0c;17页文档报告。包括图像的傅里叶滤波及压缩&#xff0c;图像的DCT高通、低通滤波&#xff0c;图像直方图均衡化&#xff0c;图像平滑与锐化&#xff0c;图像的模糊化&#xff0c;哈夫曼编码等&#xff0c;以及GUI图形化界面。…

鸿蒙内核源码分析(任务管理篇) | 任务池是如何管理的?

任务即线程 在鸿蒙内核中&#xff0c;广义上可理解为一个任务就是一个线程 官方是怎么描述线程的 基本概念 从系统的角度看&#xff0c;线程是竞争系统资源的最小运行单元。线程可以使用或等待CPU、使用内存空间等系统资源&#xff0c;并独立于其它线程运行。 鸿蒙内核每个…

在Linux中进行supervisor进程守护的安装和配置

supervisor用于守护进程&#xff0c;在进程意外终止后将其重启。 supervisor没有监听内部程序和自动重启的功能。 Python-3.9.5安装 第一步&#xff0c;检查Linux系统是否自带Python。 命令&#xff1a;python --version 第二步&#xff0c;安装依赖包。 命令&#xff1a;…

Java超市收银系统(八、数据导入)

引言 当选择1时&#xff0c;程序读取 “商品信息.xls” 文件&#xff0c;将所有数据存放于product集合中&#xff0c;然后将集合中的所有数据增加到商品表中&#xff0c;增加的时候要检查每条记录的条形码在商品表中是否存在&#xff0c;若存在&#xff0c;则不需要增加到数据库…

tortoisegit下载及其使用流程

下载 官方下载链接&#xff1a;Download – TortoiseGit – Windows Shell Interface to Git 选择适合自己的电脑位数的版本&#xff1a;一般64的兼容32的 按照就不介绍了怎么开心怎么来&#xff0c;本篇暂时为了支持一位粉丝的疑惑 安装的话没有特殊配置暂不介绍&#xff0c…

Dbeaver连接达梦数据库教程(图文版)

本章教程&#xff0c;主要介绍如何用Dbeaver连接国产达梦数据库。 达梦数据库Docker部署教程参考&#xff1a;https://yang-roc.blog.csdn.net/article/details/141158807 一、Dbeaver安装包下载 下载Dbeaver&#xff1a;https://dbeaver.io/ 在这里就不演示安装过程了&#xf…

GPU驱动的大规模静态物件渲染

GPU Driven 的静态物件渲染&#xff0c;听起来很高级&#xff0c;其实具体操作很简单&#xff0c;基础就是直接调用 Graphics.DrawMeshInstancedIndirect 这个 Unity 内置接口就可以了。但我们项目对这个流程做了一些优化&#xff0c;使得支持的实体数量有大幅提升。 这套系统主…

海南云亿商务咨询有限公司引领抖音电商新潮流

在当今这个数字化时代&#xff0c;电商行业如日中天&#xff0c;而抖音作为短视频与社交电商完美融合的典范&#xff0c;正以前所未有的速度改变着人们的购物习惯和消费模式。在这片充满机遇与挑战的蓝海中&#xff0c;海南云亿商务咨询有限公司凭借其敏锐的市场洞察力和专业的…

【算法/学习】:flood算法

✨ 君子坐而论道&#xff0c;少年起而行之 &#x1f30f; &#x1f4c3;个人主页&#xff1a;island1314 &#x1f525;个人专栏&#xff1a;算法学习 &#x1f680; 欢迎关注&#xff1a;&#x1f44d;点赞 &…

鸿蒙交互事件开发01——点击/拖拽/触摸事件

如果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧&#xff01;扫描下方名片&#xff0c;关注公众号&#xff0c;公众号更新更快&#xff0c;同时也有更多学习资料和技术讨论群。 1 概 述 事件是人机交互的基础&#xff0c;鸿蒙开发中&#xff0c;事件分…

EmguCV学习笔记 VB.Net 2.1 颜色空间和颜色

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 EmguCV学习笔记目录 Vb.net EmguCV学习笔记目录 C# 笔者的博客网址&#xff1a;VB.Net-CSDN博客 教程相关说明以及如何获得pdf教程…

威胁组织伪造Loom,Mac用户警惕AMOS窃取软件威胁

近期&#xff0c;一个复杂且可能与神秘威胁组织“Crazy Evil”有关联的网络犯罪活动&#xff0c;已将注意力转向了Mac用户群体。该组织利用广受欢迎的屏幕录制工具Loom作为掩护&#xff0c;悄无声息地传播着臭名远扬的AMOS数据窃取软件。Moonlock Lab的安全研究员们揭开了这一阴…

【数据结构与算法 | 图篇】拓扑排序

1. 概念 拓扑排序是是一种针对有向无环图进行的排序方法。它将图中所有顶点排成一个线性序列&#xff0c;使得对于图中的每一条有向边(u, v)&#xff0c;顶点u在序列中都出现在顶点v之前。 适用范围&#xff1a; 拓扑排序只适用于有向无环图。 结果非唯一&#xff1a; 对于…

阿里云ubuntu系统安装mysql8.0

一、安装mysql8.0 1.已安装其他版本的mysql&#xff0c;需要删除 若没有不需要此操作 1 #卸载MySQL5.7版本 2 apt remove -y mysql-client5.7* mysql-community-server5.7* 4 # 卸载5.7的仓库信息 5 dpkg-l | grep mysql | awk iprint $2} | xargs dpkg -P2.更新仓库 apt u…

FASTSPEECH 2论文阅读

FASTSPEECH 2: FAST AND HIGH-QUALITY END-TOEND TEXT TO SPEECH 现状 非自回归模型可以在质量相当的情况下显著快于先前的自回归模型合成模型。但FastSpeech模型训练依赖与自回归教师模型进行时长预测&#xff08;提供更多的信息作为输入&#xff09;和知识蒸馏&#xff08;…

【开端】Java中判断一个对象是否是空内容

一、绪论 在Java中&#xff0c;我们常常使用的到的就是封装&#xff0c;为什么要封装&#xff0c;封装有什么好处。首先在系统开发过程中&#xff0c;其实很多功能和场景都共性的。那么为了避免重复造轮子&#xff0c;我们这时就使用到了封装。封装可以一次造轮子&#xff0c;无…