从根上理解 mysql -一行数据是怎么存储的

前提知识-字符集

  • ascii:每个字符一个字节,只能存空格、标点符号、数字、大小写字母和一些不可见字符,不能存汉字
  • gbk:每个字符 1-2个字节
  • utf-8:每个字符1-3个字节

compact 行格式

在这里插入图片描述

解释说明

  • 变长字段长度列表:针对 VARCHAR(M)、VARBINARY(M)、各种TEXT类型,各种BLOB类型的数据,记录实际占用的字节数(为null的字段不存储)。逆序存放

  • NULL值列表:记录允许存储null的列(主键列、被NOT NULL修饰的列都是不可以存储NULL值的除外),用二进制位表示该列是否为null。 同样也是逆序存放 但是整数字节存储,不足则填充

  • 记录头信息:固定5个字节(40位)
    · 预留位1:1b
    · 预留位2:1b

    · delete_mask: 1b 删除标志。删除后只是打一个标识,所有的删除记录会组成一个删除链表。避免移除之后重新排序消耗性能。删除的空间可以被重用
    · min_rec_mask:1b B+树的每层非叶子节点中的最小记录都会添加该标记
    · n_owned
    · heap_no:13b 这个属性表示当前记录在本页中的位置。其中,每页都会新增两个虚拟记录,最大和最小
    · record_type:3b 0表示普通记录,1表示B+树非叶节点记录,2表示最小记录,3表示最大记录
    · next_record:16b 下一个记录的偏移量

  • 记录真实的数据

    • 隐藏列-rowId 非必须 无主键的是 系统自动生成
    • 隐藏列-transaction_id 事务id
    • 隐藏列-roll_pointer 回滚指针 mvcc
    • 其他真实字段数据

备注:char类型,虽说是固定长度类型,但如果字符集为gkb 或者utf8的时候,实际存储的字节也是无法确定的,因此也会在变长字段长度列表中。和varchar的区别是:CHAR(M)类型的列要求至少占用M个字节(哪怕存一个字符a),而VARCHAR(M)却没有这个要求

Redundant行格式

暂不关注

VARCHAR(M)最多能存储的数据

mysql 一条记录最大的存储空间(不包括隐藏列和记录头信息) <=65535

即:加入只存储一个varchar字段,至少有3部分

  1. 真实数据
  2. 真实数据占用字节的长度-最大2字节
  3. NULL标识(如果有的话)最大1个字节

so 若字符集选择ascii,那最大长度为65532,如果设置了not null 那最大长度为65533。
同理,
如果是gbk则 65532/2
如果是utf-8,则 65532/3

问题来了: innodb 中一页只有16kb,即16384个字节。这样可能存在一页无法存储一行数据的情况。

如果某一列中的数据非常多的话,在本记录的真实数据处只会存储该列的前768个字节的数据和一个指向其他页的地址,然后把剩下的数据存放到其他页中,这个过程也叫做行溢出
在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值