4.1.索引组织表
1.什么是索引组织表?
在innoDB存储引擎中,表都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表。
2.innoDB是怎么选择或创建主键的?
在innoDB存储引擎中,每个表都有一个主键,如果在创建表时没有显示地定义主键,则innoDB会按以下方式选择或创建主键:
1.首先判断表中是否有非空的唯一索引(Unique NOT NULL),如果有,则该列为主键
2.如果不符合条件1,则innoDB存储引擎自动创建一个6字节大小的指针
当表中有多个非空唯一索引时,innoDB存储引擎将选择建表时第一个定义的非空唯一索引为主键。
4.2 innoDB逻辑存储结构
表空间(table space)。表空间又由段(segment),区(extent),页(page,有时称为块block)组成。从innoDB存储引擎的逻辑存储结构看,所有数据都被逻辑地存放在一个空间中,称之为
1.表空间
表空间可以看做是innoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。
2.段
从图中可以看出,表空间是由段组成的,常见的段有数据段,索引段,回滚段等。
1.数据段为B+树的叶子节点,对应上图的Leaf node segment
2.索引段为B+树的非索引节点,对应上图的Non-leaf node segment
3.回滚段较为特殊,将在后续进行介绍
3.区
区是由连续页组成的空间,在任何情况下每个区的大小都为1MB,每个区中默认有64个连续的页。
4.页
页是innoDB磁盘管理的最小单位,默认大小为16KB(可以通过参数调整大小)
常见的页类型有:
1.数据页(B-tree Node)
2.undo页(undo Log Page)
3.系统页(System Page)
4.事务数据页(Transaction system Page)
5.插入缓冲位图页(Insert Buffer Bitmap)
6.插入缓冲空闲列表页(Insert Buffer Free List)
7.未压缩的二进制大对象页(Unocomp86ressed BLOB Page)
8.压缩的二进制大对象页(compressed BLOB Page)
5.行
innoDB存储引擎是面向列的,也就是说数据是按行进行存放的。
每个页存放的行记录也是有硬性定义的,最多允许存放16KB/2-200行的记录,即7992行。
4.3 innoDB行记录格式
在innoDB1.0.版本之前,innoDB存储引擎提供了compact和redundant两种格式来存放行记录数据。Redundant格式是为兼容之前版本而保留的,在MySQL5.1版本中,默认设置为Compact行格式
4.3.1 Compact 行记录格式
4.3.3 行溢出数据
InnoDB存储引擎可以将一条记录中的某些数据存储在真正的数据页面之外。
1.行溢出模型
在Compact和Redundant中,当发生行溢出时,数据存放在页类型为BLOB Page中。
2.行溢出例子
在innoDB引擎中,一个页的大小为16KB。
而我们在定义列的时候,可以看到
create table test(
a VARCHAR(65535)
)
定义VARCHAR的长度最大为65535。
问题:那么为什么页的大小为16KB,也就是16×1024=16384 能存放65535个字节呢?
回答:因为在一般情况下,innoDB存储引擎的数据都是存放在页类型为B-tree node中。但是当发生行溢出时,数据存放在页类型为Uncompress BLOB页中。
3.一个页至少应该有两条行记录
问:对于一个数据类型(可以是VARCHAR,TEXT或BLOB),什么时候是保存在单个数据页中的,又从多长开始会保存在BLOB页中呢?
答:应该满足每个页中至少应该有两条行记录的情况下。因为innoDB存储引擎表是索引组织的,即B+Tree的结构,如果不满足,则失去了B+Tree的意义,变成链表了。
4.3.4 Compressed和Dynamic行记录格式
Compressed和Dynamic对于存放在BLOB中的数据采用了完全的行溢出的方式。
如图所示,在数据页中只存放20个字节的指针,实际的数据都存放在Off Page中。
4.3.5 CHAR的行结构存储
在多字节字符集的情况下,CHAR和VARCHAR的实际行存储基本是没有区别的,CHAR有时可被视为变长字符类型。
4.4 innoDB数据页结构
在innoDB引擎中,页是innoDB存储引擎管理数据库的最小磁盘单位,页类型为B-tree Node的页存放的就是表中行的实际数据。
innoDB数据页由以下7个部分组成:
1.File Header(文件头)
2.Page Header(页头)
3.Infimun 和 Supremum Records
4.User records(用户记录,即行记录)
5.Free space(空闲空间)
6.Page Directory(页目录)
7.File Trailer(文件结尾信息)
4.4.1 File Header
File Header用来记录页的一些头信息,由表中8个部分组成,共占用38字节
innoDB存储引擎中页的类型:
4.4.2 Page Header
Page Header用来记录数据页的状态信息,由14个部分,共占用56个字节,如表:
4.4.3 Infimum 和 Supremum Record
Infimum和Supremum Record用来限定记录的边界。infinum记录是比该页中任何主键值都要小的值,Supremum Record指比任何可能大的值还要大的值。如图:
4.4.4 User Record 和Free Space
User Record 即是实际存储行记录的内容
Free Space指的是空闲空间,是一个链表数据结构。在一条记录被删除后,该空间会被加入到空闲链表中。
4.4.5 Page Directory
Page Directory存放了记录的相对位置。有些时候这些记录指针称为槽(Slots)或目录槽(Directory Slots)。
在InnoDB中,并不是每个记录拥有一个槽,而是一个槽中可能包含多个记录,我们称之为稀疏目录(sparse directory)。
二叉查找:
1.在Slots中,记录按照索引键值的顺序存放,为的是方便利用二叉查找迅速找到记录的指针。
2.由于在innoDB引擎中,Page Directory是稀疏目录,二叉查找的结果只是一个粗略的结果,因此必须通过recorder header中的next_record来继续查找相关记录
3.B+树索引本身并不能找到具体的一条记录,能找到只是该记录所在的页。数据库把页载入到内存,然后通过Page Directory再进行二叉查找。
4.4.6 File Trailer
File Trailer用来检测页是否已经完整地写入磁盘(在写入的过程中可能发生磁盘损坏,机器关机等)。
默认情况下,innoDB存储引擎每次从磁盘读取一个页就会检测该页的完整性,即该页是否发生Corrupt。
4.5 Named File Formats机制
略
4.6 约束
4.6.1
当前几乎所有的关系型数据库都提供了约束机制,该机制提供了一条强大而简易的途径来保证数据库中数据的完整性。
一般来说,数据完整性有以下三种形式:
1.实体完整性保证表中有一个主键
2.在innoDB存储引擎表中,用户可以通过定义Primary Key或Unique Key约束来保证实体的完整性。
3.用户还可以通过编写一个触发器来保证数据完整性。
对于innoDB存储引擎而言,提供了以下几种约束:
1.Primary Key
2.Unique Key
3.Foreign Key
4.Default
5.NOT NULL
4.6.2 约束的创建和查找
1.约束的创建
约束的创建可以采用以下两种方式:
1.表建立时就进行约束定义
2.利用Alter Table命令来进行创建约束
4.6.3 约束和索引的区别
约束是一个逻辑的概念,用来保证数据的完整性,而索引是一个数据结构,既有逻辑上的概念,在数据库中还代表者物理存储的方式。
4.6.4 对错误数据的约束
在默认设置下,MySQL数据库允许非法的或不正确的数据的插入或更新,又或者可以在数据库内部将其转化为一个合法的值,如向NOT NULL的字段插入一个NULL值,MySQL数据库会将其更改为0再进行插入,因为数据库本身没有对数据的正确性进行约束。(可以通过设置参数严格审核输入的参数)
4.6.5 ENUM和SET约束
MySQL数据库不支持传统的CHECK约束,但是通过ENUM和SET类型可以解决部分这样的约束需求。
4.6.6 触发器与约束
4.7 视图
在mysql中,视图是一个命名的虚表,它由一个SQL查询来定义,可以当做表使用。
与持久表不同的是,视图中的数据没有实际的物理存储
4.7.1 视图的作用
1.视图的作用
视图的主要用途之一是被用做一个抽象装置,程序本身不需要关系基表的结构,只需要按照视图定义来获取数据或更新数据。因此,视图在一定程度上起到一个安全层的作用。
2.视图的语法
CREATE
[ OR REPLACE]
[ ALGORITHM={UNDEFINED | MERGE |TEMPTABLE}]
[ DEFINER = { user | CURRENT_USER} ]
[ SQL SECURITY { DEFINER | INVOKER} ]
VIEW view_name [ (column_list) ]
AS select_statement
[ WITH [CASCADED | LOCAL] CHECK OPTION ]
其中视图定义中的WITH CHECK OPTION针对于可更新的视图,即更新的值是否需要检查,实际使用如下:
mysql>alter view v_t
->As
->select * from t where id<10//条件
->with chek option;
这时MYSQL数据库会对更新视图插入的数据进行检查,对于不满足视图定义条件的,将会抛出一个异常,不允许视图中数据更新。在这个例子中条件则为id<10。