一、总览
MySQL逻辑存储结构从高层往低层分别是:
表空间(tablespace),段(segment),区(extent),页(page),行(row)
二、表空间
所有的数据都存放在表空间中,包含有:数据、索引、插入缓冲bitmap(如果设置了innodb_file_pertable,则每张表的表空间只有前者信息,后面的信息放在原来的共享表空间内)、回滚信息、插入缓冲索引页、系统失误信息、二次写缓冲等,不做详举。
三、段
表空间由各个段组成,常见的有数据段,索引段,回滚段等。innodb对段的管理是由引擎自身完成的,DBA不能也没有必要对其进行控制。
四、区
区由连续页组成,每个区的固定大小(任何情况下都是这个大小)是1MB,默认情况下,一个区中有64个连续页(一个页大小为16kb)。
要注意一种比较特殊的情况,启用了innodb_file_per_table后,表默认大小是96kB,是因为在每个段开始时,效用32个页大小的碎片页存放数据,后续才是64个连续页的申请。
1、分区类型
1)range分区
最常用的一种分区类型,可以根据范围将数据分区并放入不同的分区文件,比如当id<10数据放入分区1,id>10数据放入分区2。
注意利用时间进行range分区时,优化器只能对YEAR(), TO_DAYS(), TO_SECONDS(), UNIX_TIMESTAMP() 进行优化选择,不能使用自定义函数。
2)list分区
跟range分区十分相似,不同的是list是利用离散值分区的。当插入分区未定义的值时,innodb会将其当成一个事务,拒绝当次插入所有的数据。
3)hash分区
利用自定义表达式进行hash分区(表达式值仅支持非负整数)。
优势:增加、删除、合并、拆分分区更加快捷
劣势:数据分布不大均匀
4)key分区
利用mysql内部函数进行分区,ndb cluster使用md5函数分区,其他引擎使用mysql内部的哈希函数(password函数)。
与hash有同样的效果。
5)columns分区
可以利用非整形数据进行分区,并且可以利用多个列数据分区。
支持所有的整形数据(除float,decimal),日期支持date和datetime,字符串支持char,varchar,binary和varbinary。
2、子分区(又称为复合分区)
没太多说的,注意每个父分区的子分区数量一致基本就可以了。
3、性能
OLAP(分析处理)分区一般比不分区好,OLTP(事务处理)分区不一定比不分区好。但是最终还是需要测试才确定分区是否合理,比如1000w的数据不分区可能比分区快(innodb的举例,)。
4、分区和表的数据交换
1)表结构一致,并且要交换的表不能有分区
2)普通表数据必须在分区表中被包含
3)普通表不能有外键引用或被引用
4)用户需要有alter,insert,create和drop权限
数据交换不会触发触发器,auto_increment会被重置。
五、页
页类型主要有数据页、undo页、系统页、事务数据页、插入缓冲位图页、插入缓冲空闲列表页、未压缩的二进制大对象页、压缩的二进制大对象页。
此外,页区分为压缩页和非压缩页,压缩页的数据也是压缩的,需要跟innodb_page_size设置的大小区分开来(这个参数设置的页默认没有压缩)区分开来。
每页最多存放16KB/2 - 200(7992)行的记录。
数据页结构不做记录。
六、行
行数据中的float、int等数值类型实际上是以字符串形势存储的。
1、行记录格式(具体可能后续再补充博文,或者自己查阅相关资料。)
1)Compact记录格式(5.1版本后的默认类型)
保存有变长字段长度列表(最多2字节),null标志位,记录头信息,数据。
2)Rebundant记录格式(兼容版本)
保存有保存字段长度偏移列表(最多2字节),记录头信息,数据。
2、行溢出数据
行溢出是指当一页数据没法保留这一行数据的时候(实际是某页中只能存放一行记录的时候就会有行溢出,阈值为8098 varchar),会将数据存储到其他数据页,并且会用一个20字节长度的指针指向这些数据页。(uncompress blob页)
innodb存储引擎可以将一条记录中的某些数据存储在真正的数据页面之外。