你知道 mysql varchar字段是怎么存储的吗?

大家对mysql一定不陌生吧,平时我们使用一些增删改查呀,无非就是对某个数据库的一些表,一些字段进行操作,这些都是抽象的概论,那么你知道对数据页中的每一行数据,他在磁盘上是怎么存储的?

其实这里涉及到一个概念,就是行格式。

Mysql 目前有4种行格式:Redundant、Compact、Dynamic、Compressed,其中Compact和Dynamic应用较广泛,本文主要介绍Compact格式,Dynamic与Compact行格式很像,差异在于页面溢出的处理上;

Compact

格式:
变长字段(记录的长度)列表 + NULL列表 + 记录头信息 + 事务ID + 回滚指针 + 列值

这里大家只用关注:变长字段(记录的长度)列表 + NULL列表 + 记录头信息 + 列值 就行了

变长字段(记录的长度)列表:

  • 采用1-2个字节来表示一个字段的长度,逆序;
  • 字段最大长度<= 255字节用1个字节表示;大于255字节,但是实际使用字节<=127,也使用1个字节来表示;其他情况使用2个字节来表示;
  • char如果是变长字符集(GBK、UTF8)也会需要使用变长字段列表来存储字段使用的长度;

NULL列表:

  • 逆序,存储每条记录中允许为NULL的字段,将实际为NULL的字段用1表示,实际不为NULL的字段用0表示;
  • 每一列不是用一个字节来表示,而是用一个位来表示;

记录头信息:

  • 使用5个字节来表示;
  • 主要包含:该记录是否被删除,记录类型,下一条记录的相对偏移量

变长字段在磁盘中是怎么存储的?

众所周知,在MySQL里有一些字段的长度是不固定的,比如VARCHAR这种类型的字段,它里面存放的字符串可能是"java"这么一个字符串,也可能是"a"这么一个字符串。

那么如果现在有一行数据,他的几个字段为VRACHAR(10),CHAR(1),由于第一个字段的长度是变化的,那么这一行数据可能是:java a,也可能是:python a

那么mysql总得把这行数据写入磁盘文件中吧,假设mysql已经把上述两条数据写入了一个磁盘文件里,两行数据是挨在一起的,那么mysql是怎么正确的区分每一个字段的呢?

变长字段长度列表

变长字段长度列表就是来解决这个问题的,mysql 是知道我们每个字段的类型的,比如这里我们用的是VARCHAR(10) CHAR(1),假设你要读取"java a"这行数据,那么此时你先要读取第一个字段的值,那么第一个字段是变长的,到底他的实际长度是多少呢?

此时你会发现第一行数据的开头有一个变长字段的长度列表,里面会读取到一个0x04这个十六进制的数字,发现第一个变长字段的长度是4,于是按照长度为4来读第一个字段的值,就是"java",接着由于后面一个字段是CHAR(1),长度都是固定的,1个字符,于是此时就按照长度为1读取下一个字段的值。

于是最终你会读取出来"java a"这一行数据。


那么如果有多个变长字段,如何存放他们的长度?
比如一行数据有VARCHAR(10) VARCHAR(20) CHAR(2) ,3个字段,其中第一二个字段是变长字段。
那么一行数据可能是:python java go

那么在磁盘中存储时,必须在他开头的变长字段长度列表中存储几个变长字段的长度,注意变长字段长度列表是逆序存储的!

也就是说先存放VARCHAR(20)这个字段的长度,然后存VARCHAR(10)这个字段的长度。

所以一行数据实际存储可能是下面这样的:
0x04 0x06 null值列表 记录头信息 python java go


其实实际上字符串这些东西并不是直接以字符串的形式存在磁盘上的,而是根据我们数据库指定的字符集编码,进行编码之后再存储的

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值