所有数据存储结构
从小到大排列
行->页->区->段->表空间
行格式
Innodb支持的所有行格式
目前,InnoDB支持4中行记录格式,分别是 Compact、Redundant、Dynamic和Compressed 行格式。Innodb默认的行格式为**Dynamic**
Dynamic行格式
变长字段长度列表
- 对于VARCHAR、TEXT、BLOB等
**可变长读存储类型**
,需要记录**真实数据中的长度**
,从而在获取真实数据时,根据长度获取对应的数据。 - 变长字段长度列表中只存储真实
**数据不为NULL的长度**
,如果值为**NULL的数据**
,**不会存储**
在变长字段长度列表中,如果所有的字段都不是变长字段,则变长字段长度列表中没有数据 - 变长字段列表的存储顺序是真实数据的
**倒序**
- 每个字段的长度由1-2个字节存储,Varchar的最大长度为65536即 2的16次方,因此需要两个字节进行长度的存储,2^8 * 2^8 = 2^16
- 因为Innodb一页的大小为16kb即16000字节,又因为
**一个页**
中**最少存储两个数据字段**
,因此会出现一页中放不下一个数据字段的情况。这种情况下会将数据放入溢出页中,当前页的长度记录仅记录存储在本页的长度
NULL值列表
- 每个字段由
**一个bit**
位进行记录,由二进制位代表是否为NULL,可以很大程度上**节省空间**
,0为非NULL值,1为NULL值,且顺序为真实数据的**逆序存放**
- 如果真实数据中都规定了数据不为NULL,则可以不存在NULL值列表
记录头信息
真实数据列
- 每行的真实数据列中,除了实际存在的数据,还存在
**事务id列**
(最后操作该数据行的事务Id),和**回滚指针**
(前一个版本的**UndoLog**
记录)。 - 真实数据列中只存储
**非NULL**
的数据。 - 除了TEXT、BLOB等大对象类型,一个数据行中包含的信息 (除去
**两个隐藏列和记录头信息**
)长度不能超过**65535**
字节。即**可变长参数列表**
、**NULL值列表**
、**存储的数据**
总和不能超过**65535**
字节。 - 在字符集为
**Latin1**
的情况下,每个字符占**1字节**
,因此**Varchar**
类型可以存储的长度则为**65535**
-**可变长度列表**
(2)-**NULL值列表**
(1 如果没有) - 在字符集为
**utf8mb4**
的情况下,每个字符占**4字节**
,因此**Varchar**
类型可以存储的长度为(65535 - 2 - 1)/4
页
**Innodb**
中的页大小为**16kb**
- 页的节点可以分为两种,
**叶子节点**
包含**数据列**
,**非叶子节点**
,仅包含**主键**
和**索引信息**
- 查询的过程中,会先通过索引列数据进行判断,找到
**查找数据所在的页**
,将**页加载到缓冲池**
中,然后先根据**二分查找**
找到大致的槽位,再根据单向链表遍历查找到对应的记录。 - 因为查询的过程中都需要将
**页从硬盘中加载到缓冲池**
中,**唯一索引**
在读取到一条数据后就可以**停止**
搜索,**普通索引**
在读取到数据后**仍会继续往下**
读取,但因为数据页都已读取到内存中,所以查询的效率没有很大的差异。
区
**一个区包含64个页**
,即1MB
- 页与页之间是采用双向链表连接在一起,在查询的过程中,通常需要在
**页与页之间**
进行**遍历查询**
。 - 如果此时页与页之间的
**距离比较远**
,则为**随机IO**
,随机的IO的速率很慢,因此如果在页与页之间进行查询使用随机IO的话会很影响效率。因此**需要尽可能让页与页之间相邻**
,这样在页之间进行**范围查询**
时,才能使用**顺序IO**
优化查询效率。 - 因此在表的数据量较大的时候给索引分配空间时,不会以页为单位进行分配,会以
**区**
进行分配,如果表的数据量很大,可以分配多个区,虽然有一定的空间损耗,但是能让查询的时候有随机IO 优化为顺序IO
段
- 在进行范围查询时,通常是节点之间进行通过双向链表进行
**遍历查询**
,而**叶子节点**
在遍历时**只会经历叶子节点**
,**非叶子节点**
在遍历时也**只会经历非叶子节点**
。 - 因此根据这个特性,在建立索引 B+树时,需要
**将叶子节点的页与非叶子节点的页分开**
,从而叶子和非叶子节点都有自己的区,而存放区的地方叫做**段**
,存放**非叶子节点**
的段叫做**索引段**
,存放**叶子节点**
的段叫做**数据段**
。 - 段时以区为单位进行单位的分配,在建立索引时,默认就会有两个段,即
**索引段**
和**数据段**
。 - 一个段内包括很多区和碎片区
碎片区
- 节约空间,碎片区不属于某个段,而只属于表空间
- 刚开始插入表数据的时候段会以某个碎片区的单个页面来分配空间
- 当碎片区达到32个时,则会申请完整的区空间
表空间
- 独立表空间
- 系统表空间