页的结构

页是一种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. 零零总总遇到过的CSS 样式

    1:添加弹出框阴影 2:禁止文本域缩放 3:直接使用CSS 完成文本内容大小写(针对英文) 4: 文本框中的占位符 5:让table每列一样高 6:不使用js 让内容换行 word-break 7:曾 ...

  2. C#如何用IL和Emit类通过Calli来实现实例函数与静态函数的调用

    一. 介绍 最近充能看书,在书上看到函数调用可以 " 通过 ldftn 获得函数指针,然后使用 calli 指令 " 来进行调用,并说这种行为 " 类似 C 的函数指针, ...

  3. MySQL基础之数据管理【3】

    MySQL中的多表联查 --查询emp的id username age depName create table emp( id int unsigned auto_increment key, us ...

  4. HiGV ui代码流程

    在海思PDT_Init下有一个这样的函数HI_PDT_UI_Init(): 1. HI_PDT_UI_Init()函数: /*public, it should be called by main() ...

  5. docker镜像管理(二)

    docker镜像 docker镜像含有启动容器所需要的文件系统和内容,因此,其用于创建并启动docker容器 docker镜像采用分层构建机制,最底层为bootfs,其之为rootfs bootfs: ...

  6. [日常] 使用TCPDUMP和Ethereal抓包分析HTTP请求中的异常情况

    在测试功能的过程中,出现这样一种现象.前端js发起ajax请求后,在浏览器的审查元素网络状态中可以看到status为pending,等15秒以后js会把当前超时的请求取消掉,变成了红色的cancel. ...

  7. firewalld基础

    firewalld是一个基于网络区域的动态管理防火墙的守护进程.在iptables中需要理解表,链等概念,而在firewalld中需要从理解区域的概念开始 防火墙依照特定的规则允许或限制输出的数据通过 ...

  8. 远程控制服务(SSH)之Windows远程登陆Linux主机

    本篇blog同样介绍两种方式进行. 首先进行准备工作: 1.所用到的工具如下: (1)     装有Linux系统的VMware虚拟机*1 (2)     终端连接工具Xshell 6 2.将Wind ...

  9. go读取配置模块viper

    这个可以常常和cobra配合. 来个demo package main import ( "fmt" "github.com/spf13/viper" ) fu ...

  10. localStorage在不同页面之间的设置值与取值--加密 localStorage与解密localStorage

    在aa.vue页面 <template> <div> <h1>在aa页面设置值</h1> <button @click="shezhi& ...