【innodb阅读笔记】之 CHAR 的行结构存储

通常理解 varchar 是存储变长长度的字符类型,char 是存储固定长度的字符类型,在使用单字节 latin1 字符集的时候,可以发现每行的变长字段长度的列表都没有存储 char 类型的长度,如:

sql 复制代码
# 创建表结构
CREATE TABLE `mytest1` (
  `t1` char(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC

# 插入数据
insert into mytest1 select 'aaa';

# 打开 mytest1.ibd 文件,整理二进制文件数据
00 00 10 ff f3
00 00 00 00 04 13
00 00 00 00 0b 29
a2 00 00 01 15 01 10
61 61 61 20 20 20 20 20 20 20
# 我们发现 char 类型 用 20 来填充, 同时没有变长字段列表

然而,从 MySQL 4.1 版本开始,char(N) 中 N 指的是字符的长度,而不是字节的长度,也就是说在不同的字符集下,char 类型内部存储的可能不是定长的数据,如:

sql 复制代码
# 创建表结构
CREATE TABLE `mytest2` (
  `t1` char(10) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk ROW_FORMAT=DYNAMIC

# 插入语句
insert into mytest2 select 'abc';
insert into mytest2 select '我们';

# 在当前例子上,表 mytest2 的字符集是 gbk ,然后我们查看所占字节,
mysql> select t1,char_length(t1),length(t1) from mytest2 \G;
*************************** 1. row ***************************
             t1: abc
char_length(t1): 3
     length(t1): 3
*************************** 2. row ***************************
             t1: 我们
char_length(t1): 3
     length(t1): 6
2 rows in set (0.00 sec)

# 'abc' 占用 3 个字节,而我们长度为 3 占用了 6 个字节,
# 使用 hex 函数查看内部二进制数据 
mysql> select t1,hex(t1) from mytest2 \G;
*************************** 1. row ***************************
     t1: abc
hex(t1): 616263
*************************** 2. row ***************************
     t1: 我们
hex(t1): E68891E4BBAC
2 rows in set (0.00 sec)
# 因此,对于多字码的字符编码,char不再代表固定长度的字符串了

# 查询 mytest2.ibd 二进制可以发现 

# abc 数据行 
0a        # 变长字段长度为10,将 char 视为 变长字段类型
00 00 10 00 23
00 00 00 00 04 14
00 00 00 00 0b 2b
a4 00 00 01 18 01 10
61 62 63 00 00 00 00 00 00 00 # abc 具体数据

# 我们 数据行
0a        # 变长字段长度为10,将 char 视为 变长字段类型
00 00 18 ff fc
00 00 00 00 04 15
00 00 00 00 0b 2c
a5 00 00 01 19 01 10
e6 88 91 e4 bb ac 20 20 20 20 # 我们 具体数据

上述例子清楚的显示了 Innodb 存储引擎内部对 char 类型在多字节字符集类型的存储,char 被明确视为变长字符类型,对于未能占用满长度的字符还是用 0x20 填充。因此,在多字节字符集的情况下,char 和 varchar 的实际行存储基本是没有区别的。

相关推荐
诸葛思颖35 分钟前
【论文阅读笔记】FL+HC(联邦学习+层次聚类)
论文阅读·笔记·聚类
序属秋秋秋2 小时前
《Linux系统编程之进程基础》【进程优先级】
linux·运维·c语言·c++·笔记·进程·优先级
河铃旅鹿5 小时前
Android开发-java版:Framgent
android·java·笔记·学习
AA陈超8 小时前
ASC学习笔记0020:用于定义角色或Actor的默认属性值
c++·笔记·学习·ue5·虚幻引擎
IMPYLH9 小时前
Lua 的 collectgarbage 函数
开发语言·笔记·junit·单元测试·lua
思成不止于此10 小时前
深入理解 C++ 多态:从概念到实现的完整解析
开发语言·c++·笔记·学习·多态·c++40周年
谅望者11 小时前
数据分析笔记08:Python编程基础-数据类型与变量
数据库·笔记·python·数据分析·概率论
iiiiii1111 小时前
【论文阅读笔记】多实例学习方法 Diverse Density(DD):在特征空间中寻找正概念的坐标
论文阅读·人工智能·笔记·机器学习·ai·学习方法·多实例学习
inputA12 小时前
【LwIP源码学习8】netbuf源码分析
android·c语言·笔记·嵌入式硬件·学习
JM丫12 小时前
内网理论知识总结
笔记·网络安全