没有合适的资源?快使用搜索试试~ 我知道了~
声明一下W、M和L的意思:1. 假设某个字符集中表示一个字符最多需要使用的字节数为 W ,也就是使用 SHOW符集中的 W 就是 2 , ascii 字符集中的
资源详情
资源评论
资源推荐
InnoDB记录存储结构
准备工作
到现在为止, MySQL 对于我们来说还是一个黑盒,我们只负责使用客户端发送请求并等待服务
器返回结果,表中的数据到底存到了哪里?以什么格式存放的? MySQL 是以什么方式来访问的
这些数据?这些问题我们统统不知道,对于未知领域的探索向来就是社会主义核心价值观中的
一部分,作为新一代社会主义接班人,不把它们搞懂怎么支援祖国建设呢?
我们前边唠叨请求处理过程的时候提到过, MySQL 服务器上负责对表中数据的读取和写入工作
的部分是 存 储 引 擎 , 而 服务 器 又 支 持 不 同 类 型 的 存 储 引 擎 , 比 如 InnoDB 、 MyISAM 、
Memory 啥的,不同的存储引擎一般是由不同的人为实现不同的特性而开发的,真实数据在不
同存储引擎中存放的格式一般是不同的,甚至有的存储引擎比如 Memory 都不用磁盘来存储数
据,也就是说关闭服务器后表中的数据就消失了。由于 InnoDB 是 MySQL 默认的存储引擎,也
是我们最常用到的存储引擎,我们也没有那么多时间去把各个存储引擎的内部实现都看一遍,
所以本集要唠叨的是使用 InnoDB 作为存储引擎的数据的存储结构,了解了一个存储引擎的数
据存储结构之后,其他的存储引擎都是依瓢画葫芦,等我们用到了再说哈~
InnoDB页简介
InnoDB 是一个将表中的数据存储到磁盘上的存储引擎,所以即使关机后重启我们的数据还是
存在的。而真正处理数据的过程是发生在内存中的,所以需要把磁盘中的数据加载到内存中,
如果是处理写入或修改请求的话,还需要把内存中的内容刷新到磁盘上。而我们知道读写磁盘
的速度非常慢,和内存读写差了几个数量级,所以当我们想从表中获取某些记录时, InnoDB
存储引擎需要一条一条的把记录从磁盘上读出来么?不,那样会慢死, InnoDB 采取的方式
是:将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小
一般为
16
KB。也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少
把内存中的16KB内容刷新到磁盘中。
InnoDB行格式
我们平时是以记录为单位来向表中插入数据的,这些记录在磁盘上的存放方式也被称为 行格
式 或者 记录格式 。设计 InnoDB 存储引擎的大叔们到现在为止设计了4种不同类型的 行格
原创:小孩子 3月31日我们都是小青蛙
式 ,分别是 Compact 、 Redundant 、 Dynamic 和 Compressed 行格式,随着时间的推移,他
们肯定会设计出更多的行格式,但是不管怎么变,在原理上大体都是相同的。
指定行格式的语法
行格式 是在我们创建或修改表的语句中指定的
CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名称
ALTER TABLE 表名 ROW_FORMAT=行格式名称
比如我们在 xiaohaizi 数据库里创建一个演示用的表 record_format_demo ,可以这样指定它
的 行格式 :
mysql> USE xiaohaizi;
Database changed
mysql> CREATE TABLE record_format_demo (
-> c1 VARCHAR(10),
-> c2 VARCHAR(10) NOT NULL,
-> c3 CHAR(10),
-> c4 VARCHAR(10)
-> ) CHARSET=ascii ROW_FORMAT=COMPACT;
Query OK, 0 rows affected (0.03 sec)
mysql>
可以看到我们刚刚创建的这个表的 行格式 就是 Compact ,另外,我们还指定了这个表的字符
集为 ascii ,因为 ascii 字符集只包括空格、标点符号、数字、大小写字母和一些不可见字
符,所以我们的汉字是不能存到这个表里的。我们现在向这个表中插入两条记录:
表中的记录就是这个样子的:
mysql> SELECT * FROM record_format_demo;
+------+-----+------+------+
| c1 | c2 | c3 | c4 |
+------+-----+------+------+
| aaaa | bbb | cc | d |
| eeee | fff | NULL | NULL |
+------+-----+------+------+
2 rows in set (0.00 sec)
mysql>
mysql> INSERT INTO record_format_demo(c1, c2, c3, c4) VALUES('aaaa', 'bbb', 'cc', 'd'),
Query OK, 2 rows affected (0.02 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql>
演示表的内容也填充好了,现在我们就来看看各个行格式下的存储方式到底有啥不同吧~
COMPACT行格式
废话不多说,直接看图:
image_1c9g4t114n0j1gkro2r1h8h1d1t16.png-42.4kB
大家从图中可以看出来,一条完整的记录其实可以被分为 记录的额外信息 和 记录的真实数
据 两大部分,下边我们详细看一下这两部分的组成。
记录的额外信息
这部分信息是服务器为了描述这条记录而不得不额外添加的一些信息,这些额外信息分为3
类,分别是 变长字段长度列表 、 NULL值列表 和 记录头信息 ,我们分别看一下。
变长字段长度列表
前边说过 MySQL 支持一些变长的数据类型,比如 VARCHAR(M) 、 VARBINARY(M) 、各种 TEXT
类型,各种 BLOB 类型,这些变长的数据类型占用的存储空间分为两部分:
1. 真正的数据内容
2. 占用的字节数
因为如果不保存真实数据占用的字节数的话,MySQL服务器也不知道我们存储的数据究竟有
多长。在 Compact 行格式中,把所有变长类型的列的长度都存放在记录的开头部位形成一个列
表,按照列的顺序逆序存放,我们再次强调一遍,是逆序存放!我们拿 record_format_demo
表 中 的 第 一 条 记 录 来 举 个 例 子 。 因 为 record_format_demo 表 的 c1 、 c2 、 c4 列 都 是
VARCHAR(10) 类型的,也就是变长的数据类型,所以这三个列的值的长度都需要保存在记录开
头处,因为 record_format_demo 表中的各个列都使用的是 ascii 字符集,所以每个字符只需
要1个字节来进行编码,来看一下第一条记录各列内容的长度:
列名 存储内容 内容长度(十进制表示) 内容长度(十六进制表示)
c1 'aaaa' 4 0x04
c2 'bbb' 3 0x03
c4 'd' 1 0x01
又因为这些长度值需要按照列的逆序存放,所以最后 变长字段长度列表 的字节串用十六进制
表示的效果就是(各个字节之间实际上没有空格,用空格隔开只是方便理解):
01 03 04
把这个字节串组成的 变长字段长度列表 填入上边的示意图中的效果就是:
image_1c9gbruvo504dlg1qsf19nbeu878.png-37kB
由于第一行记录中 c1 、 c2 、 c4 列中的字符串都比较短,也就是说内容占用的字节数比较
小,用1个字节就可以表示,但是如果变长列的内容占用的字节数比较多,可能就需要用2个字
节来表示。具体用1个还是2个字节来表示真实数据占用的字节数, MySQL 有它的一套规则,
因为用汉字描述很长的概念很容易变得啰嗦从而让人迷惑,所以我们用公式来表示一下,首先
声明一下 W 、 M 和 L 的意思:
1. 假设某个字符集中表示一个字符最多需要使用的字节数为 W ,也就是使用 SHOW
CHARSET 语句的结果中的 Maxlen 列,比方说 utf8 字符集中的 W 就是 3 , gbk 字
符集中的 W 就是 2 , ascii 字符集中的 W 就是 1 。
2. 对于变长类型 VARCHAR(M) 来说,这种类型表示能存储最多 M 个字符,所以这个类
型能表示的字符串最多占用的字节数就是 M×W ,
3. 假设它存储的字符串占用的字节数是 L 。
剩余21页未读,继续阅读
网络小精灵
- 粉丝: 27
- 资源: 335
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0