MySQL-3 行记录的存储结构

本文同样参考小孩子写的《MySQL是怎样运行的:从根儿上理解MySQL》

来总结下,一条记录在底层的存储逻辑是怎样的。

InnoDB页简介

这个存储引擎是将表中的数据存储到磁盘上,真正的数据处理是在内存中,innodb将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,大小一般为16KB

行格式

指定行格式:

CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称

ALTER TABLE 表名 ROW_FORMAT=行格式名称

compact行格式

一条完整的记录可以被分为记录的额外信息记录的真实数据

一、记录的额外信息

是服务器为了描述这条记录而不得不额外添加的一些信息,分为:变长字段长度列表、null值列表和记录头信息。

变长字段长度列表

变长字段的数据类型如:varchar(M) 各种text类型、各种blob类型,这种变长字段中存储多少字节是不固定的,所以变长字段的存储空间分为2部分:真正的数据内容+占用的字节数。

  • 在compact行格式中,把所有变长字段的真实数据占用的字节长度都存放在记录的开头部位,从而形成一个变长字段长度列表,各变长字段数据占用的字节数按照列的顺序逆序存放
  • 这些字节选取的存储方式:如果该可变字段允许存储的最大字节数W*M超过255且真实存储的字节数超过127字节,则使用2个字节,否则使用1个字节。
  • 只存储值为非NULL的列内容占用的长度,值为NULL的列的长度是不储存的。
  • 并不是所有记录都有这个变长字段长度列表,比如说表中所有的列都不是变长的数据类型的,这一部分就不需要有。
NULL值列表

表中的某些列可能存储NULL值,如果都放到记录的真实数据中存储会很占地方,所以统一管理起来,存储到null值列表中,处理过程如下:

  • 1.首先统计表中允许存储null的列有哪些。
  • 2.如果表中没有允许存储null的列,则null值列表也不存在了。否则将每个允许存储null的列对应一个二进制位,二进制位按照列的顺序逆序排列,值为1时表示该列的值为null,值为0时,代表值不为null。
  • 3.必须用整数个字节的位表示,如果不是整数个字节,则在字节的高位补0。类推,如果有9个允许为null,则需要用2个字节来表示。
记录头信息

由固定的5个字节组成,即40个二进制位,不同的位代表不同的意思,如表示该记录是否被删除,拥有的记录数等。

  • delete_mask 标记该记录是否被删除
  • min_rec_mask,B+树的每层非叶子节点中的最小记录都会添加该标记
  • n_owned,占4位,当前记录拥有的记录数
  • heap_no,占13位,当前记录在记录堆的位置信息
  • record_type,占3位,当前记录的类型,0普通记录,1B+树非叶子节点,2最小记录,3最大记录
  • next_record,占16位,下一条记录的相对位置

delete_mask
用来标记该记录是否被删除,因为移除记录会把其他记录在磁盘上重新排列,所以只是打上删除标记,这些删除的记录会组成所谓的垃圾链表,在这个链表中记录占用的空间称之为可重用空间,之后如果有新记录插入到表中的话,可能把这些被删除的记录占用的存储空间覆盖掉

heap_no
表示当前记录在本页中的位置。
innodb自动给每个里加两个记录,称为伪记录或者虚拟记录,一个代表最小记录,一个代表最大记录,(对于一条完整的记录来说,比较记录大小就是比较主键的大小)

record_type

next_record
从当前记录的真实数据导下一条记录的真实数据的地址偏移量。下一条记录是指按照主键值有小到大顺序的下一条记录,

规定Infimum即最小记录的下一条记录就是本页中主键值最小的用户记录,而本页中主键值最大的用户记录的下一条记录是Supremum即最大记录。指针指向下一条记录的 记录头信息和真实数据之间的位置,这个位置向左读取是记录头信息,向右读取是真实数据,这样可能会提高高速缓存的命中率(字段和字段长度信息在内存中的距离更近)

innodb对于已经删除的记录,再次插入时还是会重用这部分存储空间。

二、记录的真实数据

MySQL会为每个记录默认的添加一些列(隐藏列)。

innodb表对主键的生成策略:优先使用用户自定义主键,如果没有选取一个Unique键作为主键,否则innodb会为表默认添加一个名为row_id的隐藏列作为主键。

char(M)列的存储格式
对于char类型的列来说,当列采用的是定长字符集时,该列占用的字节数不会被加到变长字段长度列表,如果采用变长字符集时,该列占用的字节数也会被加到变长字段长度列表

行溢出

对于varchar类型的列最多可以占用65535个字节,减去记录的额外信息,是65532个字节,针对不同的字符集,分别存储的字符则是65532/3 。

在compact和Reduntant行格式中,对于占用存储空间非常大的列,在记录的真实数据只会存储该列的前768个字节,把剩余的数据分散存储在几个其他的页中,然后用20个字节存储指向这些页的地址,从而找到剩余数据所在的页,这些剩余的数据也叫做行溢出,存储这些页面的叫溢出页.

Dynamic和Compressed行格式

和compact行格式的区别是把所有的字节都存储到其他页面中,只在记录真实数据处存储其他页面的地址。

原文地址:https://www.cnblogs.com/efan/p/10840397.html

时间: 2024-10-09 22:27:18

MySQL-3 行记录的存储结构的相关文章

基于binlog来分析mysql的行记录修改情况(python脚本分析)

最近写完mysql flashback,突然发现还有有这种使用场景:有些情况下,可能会统计在某个时间段内,MySQL修改了多少数据量?发生了多少事务?主要是哪些表格发生变动?变动的数量是怎么样的? 但是却不需要行记录的修改内容,只需要了解 行数据的 变动情况.故也整理了下. 昨晚写的脚本,因为个人python能力有限,本来想这不发这文,后来想想,没准会有哪位园友给出优化建议. 如果转载,请注明博文来源: www.cnblogs.com/xinysu/   ,版权归 博客园 苏家小萝卜 所有.望各

百万年薪python之路 -- MySQL数据库之 MySQL行(记录)的操作(一)

MySQL的行(记录)的操作(一) 1. 增(insert) insert into 表名 value((字段1,字段2...); # 只能增加一行记录 insert into 表名 values(字段1,字段2...); insert into 表名(id,name) values(字段1,字段2),(xx1,xx2); id,name,age 插入查询结果 语法: INSERT INTO 表名(字段1,字段2,字段3-字段n) SELECT (字段1,字段2,字段3-字段n) FROM 表2

SQL SERVER大话存储结构(2)

阅读目录(Content) 1 行记录如何存储 1.1 堆表 1.2 聚集索引表格 2 非聚集索引结构 3 非聚集索引键值内容 3.1 堆表上的非聚集索引 3.2 聚集索引表(唯一)的非聚集索引 3.3 聚集索引表(非唯一)的非聚集索引 4 非聚集索引如何查找页 如果转载,请注明博文来源: www.cnblogs.com/xinysu/   ,版权归 博客园 苏家小萝卜 所有.望各位支持! 本系列上一篇博文链接:SQL SERVER大话存储结构(1)_数据页类型及页面指令分析 回到顶部(go t

Innodb物理存储结构系列2 行记录格式

前一篇讨论了Innodb system,表空间,文件的关系及数据结构,这一篇记录下Innodb行记录的格式. 前提: 1. server层和innodb层都有自己对于record的记录格式,需要进行转换. 2. 物理文件上的记录存储,需要内存中的数据结构进行对应(任何数据都需要在内存中进行处理),进行存取的转换. 1. 测试case: create table `pp` ( `id` int(11) default null, `name1` varchar(100) default null,

SQL SERVER大话存储结构(3)_数据行的行结构

一行数据是如何来存储的呢? 变长列与定长列,NULL与NOT NULL,实际是如何整理存放到 8k的数据页上呢? 对表格进行增减列,修改长度,添加默认值等DDL SQL,对行存储结构又会有怎么样的影响呢? 什么是大对象,什么是行溢出,存储引擎是如何处理它们呢? 如果转载,请注明博文来源: www.cnblogs.com/xinysu/   ,版权归 博客园 苏家小萝卜 所有.望各位支持! 1 引入 在一个DB内,每一个table都能在sys.sysobjects中找到对应的描述,每一个列,都能从

MySQL InnoDB 逻辑存储结构

MySQL InnoDB 逻辑存储结构 从InnoDB存储引擎的逻辑结构看,所有数据都被逻辑地存放在一个空间内,称为表空间,而表空间由段(sengment).区(extent).页(page)组成.ps:页在一些文档中又称块(block). InnoDB存储引擎的逻辑存储结构大致如下: 一.表空间(table space) 表空间分为了两种,这里简单的概括一下: 1. 独立表空间:每一个表都将会生成以独立的文件方式来进行存储,每一个表都有一个.frm表描述文件,还有一个.ibd文件. 其中这个文

mysql innodb 的 逻辑存储结构

如上图: innodb 的 逻辑存储单元分成 表空间,段,区,页 4个等级 默认情况下,一个数据库 所有变共享一个 默认的表空间(tablespan).可以指定每个表一个表空间. 一个表空间管理着 多个 segment( 段 ),不固定个数 一个段管理着多个区( extent ),并且一个区是一个 1M . 一个 区 有 64 页 (page),一个页是 16K. 页是mysql 逻辑存储单元的最小单元,一个 页可以保存多行的数据. page 结构:File Header(38字节),Page

mysql之innodb存储引擎---数据存储结构

一.背景 1.1文件组织架构 首先看一下mysql数据系统涉及到的文件组织架构,如下图所示: msyql文件组织架构图 从图看出: 1.日志文件:slow.log(慢日志),error.log(错误日志),general.log(基本日志) 2.配置文件:my.cnf 3.数据库:performance_schema,mysql,information_schema,sys 4.innodb存储引擎(框中部分),主要包括有:两个日志文件ib_logfile0和ib_logfile1,由参数inn

【MySQL疑难杂症】如何将树形结构存储在数据库中(方案二 Path Enumeration)

今天来介绍把树形结构存入数据库的第二种方法--路径枚举法. 还是借用上一篇的栗子,为了方便大家查阅,我把图又原样搬过来了. 需要回答的问题依旧是这样几个: 1.查询小天的直接上司. 2.查询老宋管理下的直属员工. 3.查询小天的所有上司. 4.查询老王管理的所有员工. 方案二. Path Enumeration 路径枚举法,记录下根节点到每个子节点的路径. 先创建表: CREATE TABLE employees2( eid INT, ename VARCHAR(100), position V