mysql面试(五)

前言

本章节从数据页的具体结构,分析到如何生成索引,如何构成B+树的索引结构。
以及什么是聚簇索引,什么是联合索引

InnoDB数据结构

行数据

我看各种文档中有好多记录数据结构的,但是这些都是看完就忘的东西。在这里详细讲也没有多大用处,无非就是照本宣科而已。所以就不去一点点分析每个行数据中的详细内容,大概说一下每行的大概结构。

  1. 页是 MySQL 中磁盘和内存交互的基本单位,也是 MySQL 是管理存储空间的基本单位。
  2. 指定和修改行格式的语法如下:
    CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称
    ALTER TABLE 表名 ROW_FORMAT=行格式名称
  3. InnoDB 目前定义了4种行格式

COMPACT行格式:
在这里插入图片描述
Redundant行格式:
在这里插入图片描述
Dynamic和Compressed行格式:
这两种行格式类似于 COMPACT行格式 ,只不过在处理行溢出数据时有点儿分歧,它们不会在记录的真实
数据处存储字符串的前768个字节,而是把所有的字节都存储到其他页面中,只在记录的真实数据处存
储其他页面的地址。

数据页

前面说缓存页的时候,提过数据页的概念,那么这里详细说一下什么是数据页,以及数据页的结构是什么。
数据页,代表这块16kb大小的内存空间。里面存储了每个数据页的固定信息,和行记录数据。
大概就是这些内容,下面慢慢介绍里面每个内容。
如图:
在这里插入图片描述

数据记录

数据页中的数据记录,也就是我们上面说的行数据,这些行数据都是存放在User Records这个区域内。
当有数据需要存放的时候,先从Free Space中申请一个对应大小的空间,划分到User Records区域中,然后放入数据。当free space空间用完了,就证明这个数据页已经满了,需要新开一个数据页来继续存储数据。
如图:
在这里插入图片描述
这些数据单纯存储在这里肯定不行的,我们还需要管理一下,要不然查询的时候一个个数据页一条条数据去扒拉的话,还要数据页干啥。
首先,这些数据也是由链表方式存放在数据页中,每条数据都有一个指针来指向下一条数据。形成一个单向的链表结构。 并且,这个链表的头部和尾部是两个固定的虚拟节点,虚拟节点是存储在数据页中其他地方的。不在User Records中。
如图:
在这里插入图片描述

页目录(Page Directory)

现在已经把数据页中的所有数据记录串联起来了,但是想要查询的时候,好像还是要从头捋一遍,当然也是很耗时的。
那现在我们有了这个链表,也标记了最大数据和最小数据记录。
就可以把这个最大数据记录和最小数据记录单独存储起来,不就有了一个目录的功能么? 既然是目录了,肯定不会单纯的记录最大值和最小值咯。我们看书的时候,不也是分为一个个章节吗,这样能帮助我们更快的检索到数据所在位置。
所以为了制作这个目录, 需要将数据记录分为多个组,第一组肯定是最小数据,并且这个最小数据是单独划分出来一组,其他组的数据最多不能超过8个。然后把每个组中的最后一条记录数据地址进行单独存储。
如图:
在这里插入图片描述

查询的时候,就是通过二分法确定数据在哪个槽里面,然后获取到这个分组地址中最小记录数据地址。通过链表的指针捋一遍,查询到数据。

页面头部(Page Header)

有了上面的目录依旧是不够的,还需要得到一个数据页中存储的记录的状态信息,比如本页中已经存储了多少条记录,第一条记录的地址是什么,页目录中存储了多少个槽等等,特意在页中定义了一个叫 Page Header 的部分,它是数据页结构的第二部分,这个部分占用固定的 56 个字节,专门存储各种状态信息,大概内容如下:
在这里插入图片描述

文件头部(File Header)

数据页有了基本内容,有了介绍,有了目录。现在要做的就是把这些数据页串联起来,也形成链表的格式。File Header 作为第一个组成部分,它描述了一些针对各种页都通用的一些信息,比方说这个页的编号是多少,它的上一个页、下一个页是谁啦吧啦吧啦~ 这个部分占用固定的 38 个字节,是由下边这些内容组成的:
在这里插入图片描述

数据页和B+索引

前面我们大概说了一下数据页的结构,各个数据页可以组成一个 双向链表 ,而每个数据页中的记录会按照主键值从小到大的顺序组成一个 单向链表 ,每个数据页都会为存储在它里边儿的记录生成一个页目录 ,在通过主键查找某条记录的时候可以在 页目录 中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录。
页和记录的关系示意图如下:
在这里插入图片描述
因为这些 16KB 的页在物理存储上可能并不挨着,所以如果想从这么多页中根据主键值快速定位某些记录所在的页,我们需要给它们做个目录,每个页对应一个目录项,每个目录项包括下边两个部分:
页的用户记录中最小的主键值,我们用 key 来表示。
页号,我们用 page_no 表示。
所以我们为上边几个页做好的目录就像这样子:
在这里插入图片描述
以 页28 为例,它对应 目录项2 ,这个目录项中包含着该页的页号 28 以及该页中用户记录的最小主键值 5 。我们只需要把几个目录项在物理存储器上连续存储,比如把他们放到一个数组里,就可以实现根据主键值快速查找某条记录的功能了。比方说我们想找主键值为 20 的记录,具体查找过程分两步:
先从目录项中根据二分法快速确定出主键值为 20 的记录在 目录项3 中(因为 12 < 20 < 209 ),它对应的页是 页9 。
再根据前边说的在页中查找记录的方式去 页9 中定位具体的记录。
至此,针对数据页做的简易目录就搞定了。不过忘了说了,这个 目录 有一个别名,称为 索引 。
这些目录数据也是同样存在一个数据页中,这时候的数据页就称为目录页。
在这里插入图片描述

那当数据页的数据,上了几千几万几百万千万的时候,目录页肯定也不会是单单的几个而已。那么这些目录页也是要以同样的形式,通过前后指针形成数据页一样的链表。
在这里插入图片描述
那目录页多了,肯定也是要有查询方法的,所以目录页也会以同样的方式再统计一层目录。

在这里插入图片描述
这样一层一层的统计上去,如图。是不是看着有点熟悉? 没错,这就是B+树!
最下面的存放数据的数据页就是叶子节点,其他的目录页就称为非叶子节点或者内节点,最上面的节点也称为根节点
在这里插入图片描述

从图中可以看出来,一个 B+ 树的节点其实可以分成好多层,设计 InnoDB 的大叔们为了讨论方便,规定最下边的那层,也就是存放我们用户记录的那层为第 0 层,之后依次往上加。
之前的讨论我们做了一个非常极端的假设:存放用户记录的页最多存放3条记录,存放目录项记录的页最多存放4条记录。其实真实环境中一个页存放的记录数量是非常大的,假设,假设,假设所有存放用户记录的叶子节点代表的数据页可以存放100条用户记录,所有存放目录项记录的内节点代表的数据页可以存放1000条目录项记录,那么:
● 如果 B+ 树只有1层,也就是只有1个用于存放用户记录的节点,最多能存放 100 条记录。
● 如果 B+ 树有2层,最多能存放 1000×100=100000 条记录。
● 如果 B+ 树有3层,最多能存放 1000×1000×100=100000000 条记录。
● 如果 B+ 树有4层,最多能存放 1000×1000×1000×100=100000000000 条记录。哇咔咔~这么多的记录!!!
你的表里能存放 100000000000 条记录么?所以一般情况下,我们用到的 B+ 树都不会超过4层,那我们通过主键值去查找某条记录最多只需要做4个页面内的查找(查找3个目录项页和一个用户记录页),又因为在每个页面内有所谓的 Page Directory (页目录),所以在页面内也可以通过二分法实现快速定位记录,这不是很牛么,哈哈!

聚簇索引

上面说了B+树的构成,而这个B+树本身就是一个索引,有两个特点:

  1. 所有的记录也都是按照链表的方式排列的,排列方式是按照主键大小的顺序
  2. 叶子节点存储的就是完整的数据记录

而同时具有这两种特点的B+树就是聚簇索引,也就是说,每个表都会默认创建这个聚簇索引,不需要我们通过语句显式创建。需要注意的是,这个聚簇索引的叶子节点就是所有的数据记录,也就是说数据即索引,索引即数据。

二级索引

上面的聚簇索引只有在通过主键查询的时候才会发挥作用,但是在我们真正使用的时候,并不会全都按照主键来查询。那我们想要通过其他字段中的数据查询的时候该怎么处理?
这时候就可以用其他字段来建立一个新的B+树,不同的B+树使用不同的排序规则。比如我们上面是按照主键id建了一颗树,那这次按照另一个字段再建一颗,如图:
在这里插入图片描述
这个图中,黄色依旧是主键,蓝色是我们指定的索引字段。
● 首先是第一层的建立,这里就没有全量的数据了。为了和原本的记录关联,只用了索引字段和数据的主键id。把指定的索引字段按大小排列,如果相同的话再按主键排列。
● 第二层及以上就是通用的逻辑了,记录每页的最小索引值+页号。

当我们按照索引字段查询的时候,依旧是二分法查询。根据索引值的大小一层层的确定数据的页号所在。

最后找到索引+主键id的数据,但是这时候找到的并不是全量的数据记录。如果我们需要获取其他字段的数据,就需要拿着这些主键id,到聚簇索引中再次查询数据的全量字段,而这个动作就叫做回表查询

为什么需要再次进行回表操作,直接吧数据存在这个索引中不好吗? 那样的话,就要把我们所有的数据存储两边了。而且,如果每新建一个索引,就把数据再复制一遍吗?那多大的内存也不够用啊。所以当通过这种其他字段建立的索引树进行查询的时候,还需要再次到聚簇索引进行一次回表操作才可以获取全量的数据记录。所以这种索引记录就称为二级索引,也可以称为辅助索引

也就是说,只要是非主键建立的索引,全都是二级索引。
注意的一点,如果我们这个二级索引查询的时候,如果因为相同的数据太多,获取太多的记录页的话,就会导致获取到大量的主键id。然后拿着一批主键id再进行回表肯定会影响效率啊。

需要回表的数据越多,使用二级索引的性能就越低。本来我们建立一个二级索引,就是为了能提前筛选出更加精确的数据。如果二级索引查询一大堆数据的话,那这个索引还有使用的必要吗?
所以,在我们尽量要用数据更加散列的字段来建立索引

联合索引

既然可以使用其他字段建立索引了,那肯定也可以通过多个字段建立索引咯。可以如图:
在这里插入图片描述

这个与上面说的唯一不同区别就是,所有的记录页都增加了一个字段。优先按照第一个索引字段排序,相同的话再按照第二索引字段,依旧相同的话再按照第三索引字段。。。。最后是主键id排列。

主键依旧是只存在叶子节点中,每次查询,都要到最底层的叶子节点才可以获取主键id。
那这种通过多个字段建立的索引树就是联合索引

既然我们建立索引的时候有排序的优先顺序,当然查询的时候,条件语句也是有优先顺序的。不过这个问题不用担心,mysql的查询优化器会优化我们传入的条件字段。按照最符合索引的方式进行排列。

明白了这个联合索引的排列顺序,那清楚为什么查询的时候要按照左侧优先了吗?

  1. 无论是索引条件还是字符串like查询的时候,都是按照左侧优先排序的。比如字符串“bai%”,在索引中肯定是先梳理到“b”开头的字符。如果直接“%du”,这种形式查询,就没有办法使用索引了。
  2. 多个字段查询也是这种顺序,比如我们现在的联合索引是idx_name_phone_address
    那查询的时候,使用name+phone,就可以使用索引,但是直接用phone+address就无法用到这个二级索引了
  3. 还有排序,如果我们定义的排序规则同索引顺序相同的话,就可以直接使用索引排序。比如:order by name, phone; 但是如果反过来order by phone , name; 就无法直接使用索引进行排序了。

预告

下一章节单独列一下执行计划的各个参数定义

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

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

相关文章

聊一聊 Node.js(Express)的 req.body、req.params 和 req.query 区别和应用场景

在Node.js的Express框架中&#xff0c;处理客户端发送到服务器的数据时&#xff0c;我们主要使用req.body、req.params和req.query三个属性。这些属性虽然都是请求对象(req)的一部分&#xff0c;但它们的数据来源和用途却各不相同。本文将为大家详细解读它们的区别和使用方法。…

轻量化YOLOv7系列:结合G-GhostNet | 适配GPU,华为诺亚提出G-Ghost方案升级GhostNet

轻量化YOLOv7系列&#xff1a;结合G-GhostNet | 适配GPU&#xff0c;华为诺亚提出G-Ghost方案升级GhostNet 需要修改的代码models/GGhostRegNet.py代码 创建yaml文件测试是否创建成功 本文提供了改进 YOLOv7注意力系列包含不同的注意力机制以及多种加入方式&#xff0c;在本文…

pytest:4种方法实现 - 重复执行用例 - 展示迭代次数

简介&#xff1a;在软件测试中&#xff0c;我们经常需要重复执行测试用例&#xff0c;以确保代码的稳定性和可靠性。在本文中&#xff0c;我们将介绍四种方法来实现重复执行测试用例&#xff0c;并显示当前迭代次数和剩余执行次数。这些方法将帮助你更好地追踪测试执行过程&…

【Java题解】以二进制加法的方式来计算两个内容为二进制数字的字符串相加的结果

&#x1f389;欢迎大家收看&#xff0c;请多多支持&#x1f339; &#x1f970;关注小哇&#xff0c;和我一起成长&#x1f680;个人主页&#x1f680; &#x1f451;目录 分析&#xff1a;&#x1f680; 数字层面分析⭐ 字符串层面分析⭐ 代码及运行结果分析:&#x1f6…

生活实用英语口语“拆迁”用英文怎么说?柯桥成人学英语到蓝天广场

● 1. “拆迁”英语怎么说&#xff1f; ● 01. 其实国外也有拆迁 但国外的拆迁&#xff0c;只管拆 不管安置&#xff0c;你爱去哪去哪 英文可以说 housing removal 02. 但我们中国的“拆迁” 既管“拆”也管“迁” &#xff08;还是中国人幸福~&#xff09; 英文可以说 housin…

网络安全基础知识及安全意识培训(73页可编辑PPT)

引言&#xff1a;在当今数字化时代&#xff0c;网络安全已成为企业和个人不可忽视的重要议题。随着互联网的普及和技术的飞速发展&#xff0c;网络威胁日益复杂多变&#xff0c;从简单的病毒传播到高级持续性威胁&#xff08;APT&#xff09;、勒索软件攻击、数据泄露等&#x…

【Python】Facebook开源时间序列数据预测模型Prophet

文章目录 一、简介二、项目的文件解读三、Prophet类主要方法和参数3.1 主要参数3.2 主要方法 四、用法示例 一、简介 Prophet 是由 Facebook 开发的一个开源工具&#xff0c;用于时间序列数据的预测。它特别适用于处理具有强季节性和趋势的时间序列数据&#xff0c;并且对节假…

09-软件易用性

易用性是用户体验的一个重要方面&#xff0c;网站建设者一般会沉溺于自己的思维习惯&#xff0c;而造成用户使用的不畅。易用性不仅是专业UI/UE人员需要研究&#xff0c;对于网站建设其他岗位的人也应该了解一定的方法去检验和提升网站的易用性。通常对易用性有如下定义: 易理解…

【iOS】isMemberOfClassisKindOfClass

目录 前言class方法isMemberOfClass和isKindOfClass实例方法分析类方法分析 实例验证总结 前言 认识这两个方法之前&#xff0c;首先要了解isa指向流程和继承链&#xff08;【iOS】类对象的结构分析&#xff09;关系&#xff0c;以便理解得更透彻 上经典图&#xff1a; 要注意…

AM62x和rk3568的异同点

AM62x 和 RK3568 是两款不同的处理器&#xff0c;分别来自 Texas Instruments&#xff08;TI&#xff09;和 Rockchip。它们在设计目标、架构、性能和应用领域等方面存在一些异同。以下是这两款处理器的对比&#xff1a; 1. 基本架构 AM62x&#xff1a; 架构&#xff1a;基于…

机器学习数学基础(1)--线性回归与逻辑回归

声明&#xff1a;本文章是根据网上资料&#xff0c;加上自己整理和理解而成&#xff0c;仅为记录自己学习的点点滴滴。可能有错误&#xff0c;欢迎大家指正。 1 线性回归和逻辑回归与机器学习的关系 线性回归属于机器学习 – 监督学习 – 回归 – 线性回归&#xff0c; 逻辑…

Maven概述

目录 1.Maven简介 2.Maven开发环境搭建 2.1下载Maven服务器 2.2安装&#xff0c;配置Maven 1.配置本地仓库地址 2.配置阿里云镜像地址 2.3在idea中配置maven 2.4在idea中创建maven项目 3.pom.xml配置 1.项目基本信息 2.依赖信息 3.构建信息 4.Maven命令 5.打包Jav…

企业微信报错,api forbidden 错误码 48002

业务场景是这边后端页面点同步就去企微接口拉取客户数据&#xff0c;然后报错如下。 后端抓包返回的json如下 {“errcode”:48002,“follow_user”:[],“errmsg”:“api forbidden, hint: [1721869790252850672734303], from ip: 203.88.203.216, more info at https://open.w…

数据结构(链表)

&#x1f30f;个人博客主页&#xff1a;心.c 前言&#xff1a; 最近练习算法回去学了链表&#xff0c;收获挺大的&#xff0c;大概内容整理了一下&#xff0c;语言是用c写的&#xff0c;所以在这里分享给大家&#xff0c;希望大家可以有所收获 &#x1f525;&#x1f525;&…

2024年技校大数据实验室建设及大数据实训平台整体解决方案

随着信息技术的迅猛发展&#xff0c;大数据已成为推动产业升级和社会进步的重要力量。为适应市场需求&#xff0c;培养高素质的大数据技术人才&#xff0c;技校作为职业教育的重要阵地&#xff0c;亟需加强大数据实验室的建设与实训平台的打造。本方案旨在提出一套全面、可行的…

二维码的生成与识别(python)

二维码生成 from PIL import Image import qrcode from qrcode.image.styledpil import StyledPilImage from qrcode.image.styles.colormasks import SolidFillColorMask from qrcode.image.styles.moduledrawers import SquareModuleDrawer# 创建二维码对象 qr qrcode.QRCo…

vue3在元素上绑定自定义事件弹出虚拟键盘

最近开发中遇到一个需求: 焊接机器人的屏幕上集成web前端网页, 但是没有接入键盘。这就需要web端开发一个虚拟键盘,在网上找个很多虚拟键盘没有特别适合,索性自己写个简单的 图片: 代码: (代码可能比较垃圾冗余,也没时间优化,凑合看吧) 第一步:创建键盘组件 为了方便使用…

【Django】 读取excel文件并在前端以网页形式显示-安装使用Pandas

文章目录 安装pandas写views写urls安装openpyxl重新调试 安装pandas Pandas是一个基于NumPy的Python数据分析库&#xff0c;可以从各种文件格式如CSV、JSON、SQL、Excel等导入数据&#xff0c;并支持多种数据运算操作&#xff0c;如归并、再成形、选择等。 更换pip源 pip co…

Flink SQL 实时读取 kafka 数据写入 Clickhouse —— 日志处理(三)

文章目录 前言Clickhouse 表设计adlp_log_local 本地表adlp_log 分布式表 Flink SQL 说明创建 Source Table (Kafka) 连接器表创建 Sink Table (Clickhouse) 连接器解析 Message 写入 Sink 日志查询演示总结 前言 在之前的文章中&#xff0c;我们总结了如何在 Django 项目中进…

构建智慧水利系统,优化水资源管理:结合物联网、云计算等先进技术,打造全方位、高效的水利管理系统,实现水资源的最大化利用

本文关键词&#xff1a;智慧水利、智慧水利工程、智慧水利发展前景、智慧水利技术、智慧水利信息化系统、智慧水利解决方案、数字水利和智慧水利、数字水利工程、数字水利建设、数字水利概念、人水和协、智慧水库、智慧水库管理平台、智慧水库建设方案、智慧水库解决方案、智慧…