页的结构

页是一种InnoDB管理存储空间的基本单位,它一般大小在16kb左右。实际上存在着许多不同类型的页,我们这次主要介绍的页是用来存储数据的,也叫做索引页。

接下来看看索引页的结构图:

比较重要的有三块区域:

  • Infimum + supremum
  • User Records
  • Page Directory

很明显里面叫User Records的空间就是储存行记录的地方,而Free Space其实就是页中尚未使用的空间,其他两个区域后面会解释到。

记录在页中的存储

先来回顾下简化版的行记录结构:

这其中c1,c2,c3就是真实的数据,头信息在页中发挥着至关重要的作用:

  • delete_mask: 删除标识,标识这行记录是否被删除
  • min_rec_mask:这个可以暂时先不管,属于索引的内容
  • n_owned: 稍后会提及
  • heap_no:表示记录在本页中的位置,注意这个字段的起始值是2。那么0和1呢?InnoDB会自动给每个页增加两个记录,一个代表最大记录,一个代表最小记录。还记得前面的Infimum + supremum空间吗?就是用来存这两个记录的。

    所以一个页中所有的记录都是按照主键大小的顺序排列的(这很重要
  • record_type:表示当前记录的类型,也可以暂时不管
  • next_record:这个字段标识了从当前记录的真实数据到下一条记录的真实数据的地址偏移量。

总结一下,实际上通过heap_no和next_record,就把页中的所有记录按照主键值的大小串成了一个有序的单链表。

Page Directory(页目录)

现在我们知道了所有的记录都会被串成一个有序的单链表,如果我们想查找某条记录,只需要将链表遍历过去就可以了。但是毫无疑问这样的效率是十分低下的,那么在Innodb中是如何作优化的呢?

优化的过程如下:

  1. 所有的记录会被分成几组,这包括前面所说的最大最小记录

    其中最小记录所在的组只能有一条记录也就是它自己,最大记录所在的分组拥有的记录条数只能在 1~8 条之间,剩下的分组中记录的条数范围只能在是 4~8 条之间

  2. 每组的最后一条记录(也就是主键值最大的一条记录)头信息中的n_owned属性表示该记录拥有多少条记录,也就是该组内共有几条记录。
  3. 每组的最后一条记录的地址会被单独提取出来,按照顺序存在页的尾部,其实就是我们前面所说的页目录的地方。每个地址的偏移量在Innodb中被称为插槽

按照上面的规则,我们可以得到这么一副图:

可以看到有两个插槽,意味着被分为了两组,其中:

  • 最小记录的n_owned值为1,这就代表着以最小记录结尾的这个分组中只有1条记录,也就是最小记录本身。
  • 最大记录的n_owned值为5,这就代表着以最大记录结尾的这个分组中只有5条记录,包括最大记录本身还有我们自己插入的4条记录。

说了这么多条条框框,这对于加快查找又有什么用呢?别着急现在就来揭晓如何使用。

为了更明显的看出区别,我们多加几条记录,并且逻辑上调整了下结构,便于理解:


现在我们就可以利用二分法来查找,比如说我们想找主键值为10的记录,过程是这样的:

  1. 计算中间槽的位置:(0+4)/2=2,所以查看槽2对应记录的主键值为8,又因为8 < 10,所以设置low=2,high保持不变。

  2. 重新计算中间槽的位置:(2+4)/2=3,所以查看槽3对应的主键值为12,又因为12 > 10,所以设置high=3,low保持不变。

  3. 因为high - low的值为1,所以确定主键值为10的记录在槽3对应的组中。此刻我们需要找到槽3中主键值最小的那条记录,然后沿着单向链表遍历槽3中的记录。

怎么定位一个组中最小的记录呢?我们可以很轻易的拿到槽2对应的记录(主键值为8),该条记录的下一条记录就是槽3中主键值最小的记录,该记录的主键值为9。所以我们可以从这条主键值为5的记录出发,遍历槽3中的各条记录,直到找到主键值为6的那条记录即可。

由于前面规定了一个组中包含的记录条数只能是1~8条,所以遍历一个组中的记录的代价是很小的。

所以总结一下在一个页中查找指定主键值的记录的过程分为两步:

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

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

可以看到在这种情况下,通过分组设置和二分法的配合查询,会比之前直接单链表遍历的方法快太多了。

Mysql综述--数据是如何读存的?(2)的更多相关文章

  1. Mysql综述(1)数据是如何读存的

    引言 我们都知道,mysql中的索引,事务,锁等都是作为开发人员要重点掌握的知识面,但要想掌握理解好这些知识却并非易事. 其中原因之一就是这些概念都过于抽象,事实上如果都不懂mysql数据是以一种怎样 ...

  2. mysql一张表到底能存多少数据?

    前言 程序员平时和mysql打交道一定不少,可以说每天都有接触到,但是mysql一张表到底能存多少数据呢?计算根据是什么呢?接下来咱们逐一探讨 知识准备 数据页 在操作系统中,我们知道为了跟磁盘交互, ...

  3. 了解 MySQL的数据行、行溢出机制吗?

    目录 一.行 有哪些格式? 二.紧凑的行格式长啥样? 三.MySQL单行能存多大体量的数据? 四.Compact格式是如何做到紧凑的? 五.什么是行溢出? 六.行 如何溢出? 七.思考一个问题 关注送 ...

  4. mysql 的数据文件

    mysql的数据文件 由于mysql的数据文件结构主要跟mysql的存储引擎相关,这里不做过多解释,具体查看各个引擎章节的内容 .首先上一段小辉老师的教程; 在MySQL 中每一个数据库都会在定义好( ...

  5. mysql导入数据load data infile用法

    mysql导入数据load data infile用法 基本语法: load data [low_priority] [local] infile 'file_name txt' [replace | ...

  6. mysql更改数据文件目录及my.ini位置| MySQL命令详解

    需求:更改mysql数据数据文件目录及my.ini位置. 步骤: 1.查找my.ini位置,可通过windows服务所对应mysql启动项,查看其对应属性->可执行文件路径,获取my.ini路径 ...

  7. MySQL 是如何解决幻读的

    MySQL 是如何解决幻读的 一.什么是幻读 在一次事务里面,多次查询之后,结果集的个数不一致的情况叫做幻读. 而多出来或者少的哪一行被叫做 幻行 二.为什么要解决幻读 在高并发数据库系统中,需要保证 ...

  8. 【1】MySQL大数据量分页查询方法及其优化

    ---方法1: 直接使用数据库提供的SQL语句---语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N---适应场景: 适用于数据量较少的情况(元组百/千 ...

  9. 利用Flume将MySQL表数据准实时抽取到HDFS

    转自:http://blog.csdn.net/wzy0623/article/details/73650053 一.为什么要用到Flume 在以前搭建HAWQ数据仓库实验环境时,我使用Sqoop抽取 ...

随机推荐

  1. asp.net core 新建area使用asp-action,asp-controller不管用

    解决方法: 在新建的Area目录下,这里使用Admin,Admin/Views下新建_ViewImports.cshtml和_ViewStart.cshtml两个视图文件,复制项目自动生成的到对应的新 ...

  2. python基础(14):生成器、列表推导式

    1. 生成器 什么是⽣成器?⽣成器实质就是迭代器. 在python中有三种⽅式来获取⽣成器: 1. 通过⽣成器函数 2. 通过各种推导式来实现⽣成器 3. 通过数据的转换也可以获取⽣成器 ⾸先,我们先 ...

  3. 30段极简Python代码:这些小技巧你都Get了么

    学 Python 怎样才最快,当然是实战各种小项目,只有自己去想与写,才记得住规则.本文是 30 个极简任务,初学者可以尝试着自己实现:本文同样也是 30 段代码,Python 开发者也可以看看是不是 ...

  4. MySQL学习——操作表里的数据

    MySQL学习——操作表里的数据 摘要:本文主要学习了使用DML语句操作表里数据的方法. 插入数据 语法 通过传入数据插入: insert into 表名 [(列名1, …, 列名n)] values ...

  5. GO基础之变量的使用

    Go语言:是静态类型语言,因此变量(variable)是有明确类型的,编译器也会检查变量类型的正确性. 一.基本类型 变量的声明:全局变量必须有关键字var var name [type]  指定数据 ...

  6. IAP15W4K58S4引脚定义 STC15

  7. docker系列(三):docker容器

    1 引言 在前面博文中,我们介绍了镜像.如果说镜像犹如面向对象中的类,本节要说的容器就是由类实例化出来的对象了,有了类才可以创建容器. 先从拉取一个官方提供的ubuntu最新镜像: $ docker ...

  8. Python—函数基础篇

    https://www.cnblogs.com/littlefivebolg/p/9017449.html Python 解释器的内置函数 内置函数 作用 实例 abs() 返回数字的绝对值. abs ...

  9. toast文本提示信息元素获取

    在做自动化的过程中,我们有可能会遇到toast提示语,这种提示语只会显示一两秒的样子,导致我们获取元素很困难 今天总结下怎么获取这个toast元素吧 例如下图所示的这种toast提示 图中红框的这种元 ...

  10. c# WF 第6节 MDI窗体

    本节内容: 1:SDI 窗体是什么 2: MDI 窗体是什么 3:如何创建MDI窗体 1:SDI 窗体是什么 SDI 窗体 : single-document interface 单一的窗体:上篇的启 ...