页的结构

页是一种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. 科技风商务项目管理PPT模板

    模板来源:http://ppt.dede58.com/peixunyanjiang/26267.html

  2. 关于spring,IOC和AOP的解析原理和举例

    引用自:https://blog.csdn.net/paincupid/article/details/43152397 IOC:就是DAO接口的实现不再是业务逻辑层调用工厂类去获取,而是通过容器(比 ...

  3. C++ 手把手教你实现可变长的数组

    01 实现自定义的可变长数组类型 假设我们要实现一个会自动扩展的数组,要实现什么函数呢?先从下面的main函数给出的实现,看看有什么函数是需要我们实现的. int main() { MyArray a ...

  4. BayaiM__linux双网卡绑定文档

    BayaiM__linux双网卡绑定文档 开门贱山:以下内容纯属原创,如有雷同,爱咋咋滴吧~~!!—————————————————————————————————————————— 1,备份网卡信息 ...

  5. 删除带外键的表【foreign key constraint fails】报错

    title: 删除带外键的表[foreign key constraint fails]报错 date: 2018-08-02 21:59:06 tags: 数据库 --- 遥想当时正在学hibern ...

  6. mmap - 内存映射文件 - 减少一次内核空间内数据向用户空间数据拷贝的操作

    关于mmap 网上有很多有用的文章,我这里主要记录,日常使用到mmap时的理解: https://www.cnblogs.com/huxiao-tee/p/4660352.html 测试代码: htt ...

  7. C学习笔记(10)--- 强制类型转换,错误处理,递归

    1.强制类型转换: 强制类型转换是把变量从一种类型转换为另一种数据类型.例如,如果您想存储一个 long 类型的值到一个简单的整型中,您需要把 long 类型强制转换为 int 类型. 您可以使用强制 ...

  8. Firefox 与 geckodriver 版本兼容问题

    打开 python shell,执行以下脚本: from selenium import webdriverdriver = webdriver.Firefox()driver.maximize_wi ...

  9. char数据类型

    char数据类型就是为了中文 一个中文占两个字节正好char是占用两个字节 char a='国'’; char类型必须使用单引号属于字符类型 双引号的是字符串类型如果使用等号两边数据类型不一致就是 不 ...

  10. 1【西北师大-2108Java】第一次作业成绩汇总

    [西北师大-2108Java]第一次作业成绩汇总 经过本次作业的练习,了解了Java最基本的知识和Java的发展:了解了Java到底是一门怎样的语言,也知道了学习Java的乐趣,懂得了去选择Java开 ...