MySQL技术内幕InnoDB存储引擎 第四章 表

来源:互联网 发布:ftpflashfxp mac 编辑:程序博客网 时间:2024/06/06 15:28

1.

所有数据都被逻辑存放在一个空间中,称之为表空间。表空间又由段(segment),区(extent),页(page)组成。

表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有数据都存放在表空间中。

默认情况下有一个空享表空间ibdata1,所有数据都放在这个表空间内。若启用了innodb_file_per_table,则每张表内的数据可以单独放到一个表空间内。

an extent = 64 pages.

对于启用了innodb_file_per_table,每张表的表空间内存放的只是数据,索引,和插入缓冲,其他类的数据,如撤销信息,系统事务信息,二次写缓冲等还是存放在原来的共享表空间内。这也就说明了共享表空间是会不断增加大小的。


表空间是由各段组成的,常见的有数据段,索引段,回滚段。因为InnoDB存储引擎表是索引组织的,因此数据即索引,索引即数据。那么数据段即为B+数的页结点,索引段即为B+树的非索引节点。并不是每个对象都有段。


区有由64个连续的页组成的,每个页为16KB,即每个区1MB。对于大的数据段,InnoDB存储引擎每次做多可以申请4个区,以此来保证数据的顺序性能。

在启用innodb_file_per_table后,创建的表默认大小是96KB。在每个段开始时,先有32个页大小的碎片页来存放数据,当这些页使用完之后才是64连续页的申请。


页是InnoDB磁盘管理的最小单位。

常见的页类型有:

数据页

Undo页

系统页

事务数据页

插入缓冲位图页

插入缓冲空闲列表页

未压缩的二进制大对象页

压缩的二进制大对象页


InnoDB存储引擎是面向行的,也就是说数据的存放按行进行存放。每个页存放的行记录也是有硬性定义的,最多存放7992行记录。


2.

从物理意义上来看,InnoDB表由共享表空间、日志文件组、表结构定义文件组成。


InnoDB存储引擎提供了Compact和Redundant两种格式来存放行记录数据,Redundant是为兼容之前版本而保留的。默认为Compact格式。


Compact行记录格式

其设计目标是高效存放数据。简单来说,如果一个页存放的行数据越多,其性能就越高。以如下方式进行存储

变长字段长度列表     NULL标志位    记录头信息      列1数据     列2数据............................

变长字段长度列表  是按照列的顺序逆序放置的。列的长度小于255字节,用1字节表示,若大于255个字节,用2个字节表示,变长字段的最大长度不可以超过2个字节(这解释了为什么MySQL中varchar的最大长度为65535)。

还需注意的是InnoDB每行有隐藏列。固定长度char字段在未充满其长度时用0x20来进行填充。

记录头信息的最后4个字节代表next_recoder.InnoDB存储引擎在也内部是通过一种链表的结构来串联各个记录。


第三行有NULL值,因此NULL标志位不再是00而是06了,转换成二进制位00000110,为1的值代表了第2列和第3列的数据为NULL,只存储了第1列和第4列非NULL的值。这个例子很好地说明了:不管是char还是varchar,NULL值是不占用存储空间的。


Redundant行记录格式

字段长度偏移列表     记录头信息   列1数据  列2数据  ...............................

mytest2.ibd中 23 20 16 14 13 0c 06,逆转为06,0c,13,14,16,20,23.分别代表第一列长度6,第二列长度6(6+6=0x0C),第三列长度7(6+6+7=0x13),第四列长度1(6+6+7+1=0x14)。。。。


行溢出数据

InnoDB存储引擎表示索引组织的,即B+树结构。因此每个页中至少应该有两行记录(否则失去了B+树的意义,变成链表了)。因此如果页中只能存放下一条记录,那么InnoDB存储引擎会自动将行数据存放到溢出页中。


InnoDB Plugin引入了新的文件格式Compressed和Dynamic称为Barracuda。以前支持Compact和Redundant格式将其称为Antelope格式。

新的两种格式对于存放BLOB的数据采用了完全的行溢出的方式,在数据页中只存放20个字节的指针,实际的数据都存放在BLOB Page中,而之前的Compact和Redundant两种会存放768个前缀字节。

Compressed行记录格式的另一个功能是,存储在其中的行数据会以zlib的算法进行压缩,因此对于BLOB、TEXT、VARCHAR这类大长度的数据能进行非常有效的存储。


Char的行结构存储

每行的变长字段长度的列表都没有存储对于CHAR类型的长度。从MySQL4.1开始,CHAR(N)中的N指的是字符的长度,而不是之前版本的字节长度。那么字不同的字符集下,CHAR内部存储的不是定长的数据。

在InnoDB存储引擎内部对于CHAR类型在多字节字符集类型的存储,CHAR很明确地被视为了变长类型,对于未能占满长度的字符还是填充0x20.


InnoDB数据页结构

由以下七个部分组成

File Header(文件头)

Page Header(页头)

Infimun  + Supremum Records

User Records(用户记录,即行记录)

Free Space(空闲空间)

Page Directory(页目录)

File Trailer(文件结尾信息)


在InnoDB存储引擎中,每个数据页中有两个虚拟的行记录,用来限定记录的边界,Infimum记录是比该页中任何主键值都要小的值,Supremum指比任何可能大的值还要大的值。

需要牢记的是,B+树索引本省并不能找到具体的一条记录,B+树索引能找到只是该记录所在的页。数据库把页载入内存,然后通过Page Directory再进行二叉查找。只不过二叉查找的时间复杂度很低,同时内存中的查找很快,因此通常我们忽略了这部分查找所用的时间。


为了保证页能够完整地写入磁盘,InnoDB存储引擎的页中设置了File Trailer部分。File Trailer只有一个FIL_PAGE_END_LSN部分,占用8个字节。前4个字节代表该页的checksum值,后4个字节和Header的FIL_PAGE_LSN相同。


InnoDB存储引擎的槽是稀疏的,还需通过record header的n_owned进行进一步判断。如我们需要找主键a为5的记录,通过二叉查找Page Directory的槽,我们找到记录的相对位置在00e5处,找到记录的实际位置0xc0e5:
可以看到第一行的记录是4不是我们要找的内容,但是我们看前面的5个字节的record header,找到4~8位表示n_owned值的部分,该值为4,表示该记录有4个记录,因此还需要进一步查找。
通过recorder和ader最后2个字节的偏移量0x0022,找到下一个记录的位置。。


触发器的作用是在INSERT、DELETE和UPDATE命令之前或之后自动调用SQL命令或者存储过程。


最多可以为一个表建立6个触发器,即分别为INSERT、UPDATE、DELETE的BEFORE和AFTER各定义一个。


外键定义为,ON DELETE和ON UPDATE表示父表做DELETE和UPDATE操作时子表所做的操作。可定义的子表操作有,

CASCADE :当父表发生DELETE和UPDATE操作时,相应的子表中的数据也被DELETE和UPDATE.

SET NULL: 当父表发生DELETE或UPDATE操作时,相应的子表数据被更新为NULL值。

NO ACTION:当父表发生DELETE或UPDATE操作时,抛出错误,不允许这类操作发生。

RESTRICT:当父表发生DELETE或UPDATE操作时,抛出错误,不允许这类操作发生。


物化视图的刷新是指当基表发生了DML操作后,物化视图何时采用哪种方式和基表进行同步。刷新的模式有ON DEMAND和ON COMMIT.

DEMAND:在用户需要的时候进行刷新。

COMMIT:物化视图在对基表的DML操作提交的同时进行刷新。

刷新的方法有四种:FAST,COMPLETE,FORCE,NEVER.

FAST:增量刷新,只刷新自上次以后进行的修改。

COMPLETE:对整个物化视图完全的刷新。

FORCE:则Orcal刷新时会去判断是否可以快速刷新,如果可以采用FAST方式,否则采用COMPLETE方式。


MySQL数据库本身并不支持物化视图,但我们可以通过一些机制来实现物化视图的功能。



数据库的应用分为两类:一类是OLTP(在线事务处理),如博客,电子商务,网络游戏等。另一类是OLAP(在线分析处理),如数据仓库,数据集市。

对于OLAP的应用,分区的确可以很好地提高查询的性能。

0 0