热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

MYsql_回龙观大叔狂磕mysql(第二回)

篇首语:本文由编程笔记#小编为大家整理,主要介绍了回龙观大叔狂磕mysql(第二回)相关的知识,希望对你有一定的参考价值。同学,还记得上一回说的回龙观大叔面试的故事嘛?

篇首语:本文由编程笔记#小编为大家整理,主要介绍了回龙观大叔狂磕mysql(第二回)相关的知识,希望对你有一定的参考价值。


同学, 还记得上一回说的回龙观大叔面试的故事嘛? 

经过上一回合的学习, 这位大叔终于找回了点自信, 这次又投了几家公司, 不过现在还没有公司去联系他.

大叔的电脑桌放在阳台上, 这是个绝佳的位置, 每天清晨惺忪的阳光都能照进来, 但大叔可不想坐在那每天晚上数星星、白天晒太阳, 当小区里面的年轻人还在熟睡的时候, 大叔早已经坐在书桌前开始继续瞌 mysql 的知识了.

以下知识均为大叔周末聊天时的口述, 我这里整理下大概知识点.

大叔: 小兄弟, 大叔是面试的过来人, 这回合的知识很重要, 可要避免重走我的老路呀~



InnoDB管理存储空间的基本单位: 页

我把 Innodb 比喻成一本书, 那么基本存储单位就是页, 一个页的大小大约是16KB. 页的类型也不一样, 在书里面有目录页、附录页、内容页, Innodb 根据不同功能也有很多类型的页, 比如存放INODE信息的页、存放 undo 日志信息的页、存放数据索引的页等等.

这是一行数据的底层存储结构, 看看我调的色都么清新~回龙观大叔狂磕mysql(第二回)

下面大叔解释淡绿框字段的含义:


1.delete_mask



被删除的记录还在页中么? 他不会立即从页中真正的移除掉, 行记录中 delete_mask 就是标记已删除的记录, 所有被删除掉的记录都会组成一个所谓的垃圾链表,在这个链表中记录占用的空间称之为所谓的可重用空间,之后如果有新记录插入到表中的话,可能把这些被删除的记录占用的存储空间覆盖掉


如果面试官要问你, 为什么删除掉记录不真正移除掉?

你就答: 记录与记录之间是有关联关系的, 移除它们之后把其他的记录在磁盘上重新排列需要性能消耗.


2.min_rec_mask

min_rec_mask 用来标记 B+树 的每层非叶子节点中的最小记录


3.heap_no

用来标记当前记录的页位置, 页中行数据排列顺序也是从小到大顺序排列的, 值得一提的是每个页中自动加了两条虚拟记录, 一个记录的是当前页的主键最大记录, 一个记录的是最小记录. 也就是上一回合提到的每个 page页 最少两条记录的原因


4.record_type

当前行记录类型




























类型值 含义
0 普通记录(通常我们插入的数据记录)
1 B+树非叶节点记录(索引数据)
2 页最小记录(虚拟记录)
3 页最大记录(虚拟记录)


5.空间换性能 next_record


6.n_owned

n_owned 表示该组内共有几条记录

我问大叔具体这个是啥意思啊, 大叔说他没搞明白, 如果面试官继续问就说不知道就可以了, 技术圈一般都已点到为止, 不用深究.


slot

查找一条记录, 我们需要遍历所有页嘛? 在数据量少的情况, 我们可以根据页中存的最大最小记录查找, 但是数据量一多, 肯定也是无法忍受的. 那 innodb 是怎么做的呢?

我们还是拿书举例子, 书也是一页一页的, 我们怎么快速定位到某一章某一节的某一段内容呢? 聪明的小伙伴肯定回答是: 目录。

没错, 我们看看 mysql 是怎么实现页 ”页级别目录“ 的

回龙观大叔狂磕mysql(第二回)(此图为回龙观大叔所盗《mysql是怎样运行的》, 与本文作者无关)

简单来说, 就是一个 page 页中最大8条记录分组, 将每组最小最大的值偏移量记录到 slot 槽中, 这里的 slot 就相当于目录的一个作用, 下面是一个查数过程:





  1. 通过二分法确定该记录所在的槽,并找到该槽所在分组中主键值最小的那条记录





  2. 通过记录的 next_record 属性遍历该槽所在的组中的各个记录




B+树索引

听回龙观大叔说这是让他那天面试最心碎的地方, 需要我额外注意, 大家提起精神来啊~

大叔狂磕第一回我们就知道在一个数据页怎么定位数据了, 但是我们都是假设基于主键进行的查找哦。那么如果不是主键呢?



这个就很悲剧了, 因为在数据页中并没有对非主键列建立所谓的页目录,所以我们无法通过二分法快速定位相应的槽。这种情况下只能从最小记录开始依次遍历单链表中的每条记录,然后对比每条记录是不是符合搜索条件(下面会讲到索引, 解决这个遍历查询慢问题)


一个数据页大概只有 16KB, 我们数据一般不可能只有这些, 肯定需要多个数据页存储, 那么多个页之间是怎么管理的呢?

页和页之间是双向链表连接回龙观大叔狂磕mysql(第二回)(此图为回龙观大叔所盗《mysql是怎样运行的》, 与本文作者无关)



如果没有索引的话, 默认是从页a开始查知道页b、页c挨个查找, 直到满足指定的条件为止.



页分裂

当数据页数据变大时, 将会由新增页来存储新数据, 这个过程就叫 页分裂.

比如下图是在页10中插入记录主键4, 而已存在记录主键5, 当页10已满时, 新创建页28, 进行的数据调整过程.

回龙观大叔狂磕mysql(第二回)(此图为回龙观大叔所盗《mysql是怎样运行的》, 与本文作者无关)]



大家忽略页号, 这个是没有实际作用的, 真正的前后关系是使用页之间双向链表维护的.


由上面的规则可以看出, 在对页中的记录进行增删改操作的过程中, 下一个数据页中的主键值必须大于上一个页中主键值, 所以我们一般设置主键都会设置自增, 这样是可以避免页满时数据进行交换调整.

页内查询我们冗余 slot 空间来进行提高查询速度, 但是对于这么多页, 总不能一个页一个页的扫描吧. 当然不行!那我们再抽象一层.

回龙观大叔狂磕mysql(第二回)(此图为回龙观大叔所盗《mysql是怎样运行的》, 与本文作者无关)

我们看这样扫描页是不是就很快了, 我们基于上面数据就可以很快定位到具体的页了.



key 就是我们说的索引


回龙观大叔狂磕mysql(第二回)(此图为回龙观大叔所盗《mysql是怎样运行的》, 与本文作者无关)

如上图所示, 同数据页一样, 我们索引key也是也是页管理的, 还记得上面 record_type 类型么, record_type=1为 B+ 树非叶节点记录, 普通数据为 record_type=0



索引检索、slot检索都是通过二分查找算法实现的


如果数据量再大, 索引页也会变得更多, 那么我们该怎么办呢? 再抽象一层!




image.png



但是这里树的高度并不能无限扩增哦, 因为每一层都代表了一次磁盘IO, 层级高磁盘IO次数变多将会导致查询变慢. B+树本质增大层的宽度来降低树的高度, 所以一般我们树的高度也不会超过4层, 一个页节点存放1000条数据, 一层1000个节点, 四层则是1000X1000X1000X10000=100000000000!!!



聚簇索引索引

如上图, Innodb 将所有数据存在叶子节点, 我们通常称这种存储方式为聚簇索引.

我理解聚簇索引对于实现行锁是非常方便的, 主键查询条目比较少时,不用回行. 但是如果碰到不规则数据插入时,造成频繁的页分裂



MyISAM的索引方案也是树形结构,但是却将索引和数据分开存储的



回表与覆盖索引

当我们基于二级索引查找数据时, 会给二级索引同样建立一个类似的 B+ 树, 不过叶子节点存储的是主键的id, 再基于主键查询叶子节点数据, 这种行为我们称之为回表.

而我们查询字段正好与索引完全匹配, 不用再回表查询数据, 称为覆盖索引.

(此图为回龙观大叔所盗, 与本文作者无关)


联合索引

页面和记录先按照联合索引前边的列排序,如果该列值相同,再按照联合索引后边的列排序. 这种记录模式决定了我们直接使用后面的字段是无法用到索引的, 因为单独它本身就是无序的.


索引可不是银弹

如果数据行数多和建立索引数据大, 索引是消耗存储空间的.

在增删改上都需要去修改各个B+树索引, 尤其对于无序的数据索引来说, 修改顺序的后果是将会频繁的进行插入修改页、页分裂, 对于 DML 性能来说是有损耗的.

只为用于搜索、排序或分组的列创建索引

通常我们只对索引数据分布广建立索引, 对于性别类是不适合建立索引的, B+树内节点变成了二节点, 叶子节点数据聚集严重.

索引列的类型小, 对于大类型列占据更多的存储空间, 检索效果不好, 可以选定索引字符串值的前缀.


与回龙观大叔总结

上一次见回龙观大叔, 距离现在过去才几天, 上次还抱怨找工作问他底层 mysql 知识, 这次感觉非常乐于学习并向我分享这些底层基础知识了. 但是一个跟我父亲年龄相仿还每天在努力学习、找砖搬的大叔, 我不知道是应该替他担心还是高兴.



推荐阅读
  • 本文详细介绍了 PHP 中对象的生命周期、内存管理和魔术方法的使用,包括对象的自动销毁、析构函数的作用以及各种魔术方法的具体应用场景。 ... [详细]
  • 非计算机专业的朋友如何拿下多个Offer
    大家好,我是归辰。秋招结束后,我已顺利入职,并应公子龙的邀请,分享一些秋招面试的心得体会,希望能帮助到学弟学妹们,让他们在未来的面试中更加顺利。 ... [详细]
  • 从0到1搭建大数据平台
    从0到1搭建大数据平台 ... [详细]
  • 本文将详细介绍如何在Mac上安装Jupyter Notebook,并提供一些常见的问题解决方法。通过这些步骤,您将能够顺利地在Mac上运行Jupyter Notebook。 ... [详细]
  • 在什么情况下MySQL的可重复读隔离级别会导致幻读现象? ... [详细]
  • 如何在Linux服务器上配置MySQL和Tomcat的开机自动启动
    在Linux服务器上部署Web项目时,通常需要确保MySQL和Tomcat服务能够随系统启动而自动运行。本文将详细介绍如何在Linux环境中配置MySQL和Tomcat的开机自启动,以确保服务的稳定性和可靠性。通过合理的配置,可以有效避免因服务未启动而导致的项目故障。 ... [详细]
  • MySQL的查询执行流程涉及多个关键组件,包括连接器、查询缓存、分析器和优化器。在服务层,连接器负责建立与客户端的连接,查询缓存用于存储和检索常用查询结果,以提高性能。分析器则解析SQL语句,生成语法树,而优化器负责选择最优的查询执行计划。这一流程确保了MySQL能够高效地处理各种复杂的查询请求。 ... [详细]
  • 在使用 Cacti 进行监控时,发现已运行的转码机未产生流量,导致 Cacti 监控界面显示该转码机处于宕机状态。进一步检查 Cacti 日志,发现数据库中存在 SQL 查询失败的问题,错误代码为 145。此问题可能是由于数据库表损坏或索引失效所致,建议对相关表进行修复操作以恢复监控功能。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 如何精通编程语言:全面指南与实用技巧
    如何精通编程语言:全面指南与实用技巧 ... [详细]
  • 在《Cocos2d-x学习笔记:基础概念解析与内存管理机制深入探讨》中,详细介绍了Cocos2d-x的基础概念,并深入分析了其内存管理机制。特别是针对Boost库引入的智能指针管理方法进行了详细的讲解,例如在处理鱼的运动过程中,可以通过编写自定义函数来动态计算角度变化,利用CallFunc回调机制实现高效的游戏逻辑控制。此外,文章还探讨了如何通过智能指针优化资源管理和避免内存泄漏,为开发者提供了实用的编程技巧和最佳实践。 ... [详细]
  • PHP 各版本对比:标准版与最新顶级版的详细分析 ... [详细]
  • 深入解析Struts、Spring与Hibernate三大框架的面试要点与技巧 ... [详细]
  • Hadoop平台警告解决:无法加载本机Hadoop库的全面应对方案
    本文探讨了在Hadoop平台上遇到“无法加载本机Hadoop库”警告的多种解决方案。首先,通过修改日志配置文件来忽略该警告,这一方法被证明是有效的。其次,尝试指定本地库的路径,但未能解决问题。接着,尝试不使用Hadoop本地库,同样没有效果。然后,通过替换现有的Hadoop本地库,成功解决了问题。最后,根据Hadoop的源代码自行编译本地库,也达到了预期的效果。以上方法适用于macOS系统。 ... [详细]
  • 深入浅析JVM垃圾回收机制与收集器概述
    本文基于《深入理解Java虚拟机:JVM高级特性与最佳实践(第3版)》的阅读心得进行整理,详细探讨了JVM的垃圾回收机制及其各类收集器的特点与应用场景。通过分析不同垃圾收集器的工作原理和性能表现,帮助读者深入了解JVM内存管理的核心技术,为优化Java应用程序提供实用指导。 ... [详细]
author-avatar
手浪用户2502939427_143
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有