COMPACT行格式的VARVHAR(M)
compact的行格式中包含主要有:真实数据、边长字段列表、NULL值列表(如果该列没有NOT NULL属性,那么就没有这部分存储空间)。其中变长字段列表占用1个字节或者2个字节,也就是说最大就是2的16次方-1等于65535,如果有NULL值列表的话就占用1个字节。
测试一下(默认可以为NULL),c1不指定not null:
CREATE TABLE varchara_size_demo(
c1 VARCHAR(65535)
)CHARSET =ascii ROW_FORMAT=COMPACT;
提示我们行的最大就是65535,其中包含了其他信息。这里的其他信息说的就是变长字段列表和NULL
当我们指定c1的大小为65532:
系统提示是可以创建成功的,因为:65535-1(NULL值列表占用1个字节)-2(变长字段列表占用2个字节)
CREATE TABLE varchara_size_demo(
c1 VARCHAR(65532)
)CHARSET =ascii ROW_FORMAT=COMPACT;
测试一下(默认可不能为NULL),指定c1为not null:
系统提示是可以创建成功的,因为65535-2(变长字段列表占用2个字节),这里没有NULL值列表这部分的存储空间了,所以就是65533:
CREATE TABLE varchara_size_demo(
c1 VARCHAR(65533) NOT NULL
)CHARSET =ascii ROW_FORMAT=COMPACT;
行溢出
一个页的大小为16kb,也就是16384(16*1024)字节,而一个VARCHAR类型的列最多能存放65532字节,这样可能造成一个页存放不下一条记录,则需要多个页来存储一条记录。
行溢出零界点:
- Mysql中规定一个页中至少存放两条记录
- 每个页除了存放记录以外,需要存储一些元数据信息(136个字节的空间)
- 每个记录需要的元数据是27个字节
1. 2个字节的真实数据的长度
2. 1个字节用于存储列是否是NULL值
3. 5个字节的row_id列
4. 6个字节的tansaction_id列
5. 7个字节的roll_pointer列
假设一个列中存储的数据字节数为N,那么发生行溢出现象需要满足这个式子:
136+2*(27+N) > 16384
求的N > 8098。如果一个列中存储的数据大于8098个字节,那么就会发生行溢出的现象,否则不会发生行溢出的现象。
结论
- 如果VARCHAR类型的列没有NOT NULL属性,那么最多能存储65532个字节的数据。因为边长字段的列表需要占用2个字节,NULL值列表需要占用1个字节
- 如果VARCHAR类型有NOT NULL属性,那么最多存储65533个字节的数据,因为变长字段列表需要占用两个字节,不需要NULL值列表的1个字节