什么是数据页
详情点击 学习笔记-InnoDB数据页结构
什么是数据区
1. 对于InnoDB来说,每个表有一个*.idb文件。
2. 这个文件由多个段(segments)组成,每个段和一个索引相关。
3. 段会跟着构成它的更小一级单位—区的变化而变化。区仅存在于段内,并且每个区都是固定的1MB大小(页体积默认的情况下)。
4. 页则是区的下一级构成单位,默认体积为16KB。
5. 16*64=1024,也就是说一个区里面会有64个连续的数据页,连续的256个数据区为一组数据区。

InnoDB结构要求页至少要有两个行,至少两行数据才能成为树。
按这样算,一个区可以容纳最多64个页,一个页可以容纳2-N个行。
因此可以算出行的大小最多为8000 bytes。
页合并
当你删了一行记录时,实际上记录并没有被物理删除。
记录被标记(flaged)为删除,并且它的空间变得允许被其他记录声明使用。
当页中删除的记录达到MERGE_THRESHOLD(默认页体积的50%),InnoDB会开始寻找最靠近的页(前或后)看看是否可以将两个页合并以优化空间使用。
-- 查看索引信息SHOW INDEX FROM `test_innodb`;

为索引设置MERGE_THRESHOLD
ALTER TABLE `test_innodb` ADD KEY idx_id (id) COMMENT 'MERGE_THRESHOLD=40';

如果我们在UPDATE操作中让页中数据体积达到类似的阈值点,InnoDB也会进行一样的操作。
页分裂
页可能填充至100%,在页填满了之后,下一页会继续接管新的记录。
但如果某一页没有足够的空间去容纳(或更新)的记录,且下一页页同样没有足够空间。
InnoDB的做法是(简化版):
创建新页
判断当前页可以从哪里进行分裂(记录行层面)
移动记录行
重新定义页之间的关系
规律总结:页分裂会发生在插入或更新,并且造成页的错位(dislocation,落入不同的区。
非自增主键导致分裂
假设主键不是自增,那就有可能出现下面这种情况

然后随着你将数据写入。就导致后一个数据页中的所有行并不一定比前一个数据页中的行的id大。这时就会触发页分裂的逻辑。
页分裂的目的就是保证:后一个数据页中的所有行主键值比前一个数据页中主键值大。
经过分裂调整,可以得到下面的这张图

optimize
当我们使用mysql进行delete数据,delete完以后,发现空间文件*.ibd并没有减少,这是因为碎片空间的存在。
举个例子,一共公司有10号员工,10个座位,被开除了7个员工,但这些座位还是保留的,碎片整理就像,让剩下的3个员工都靠边坐,然后把剩下的7个作为给砸掉,这样就能释放出空间了。
为了更加直观的看到数据碎片,Mysql可以使用如下命令查看
show table status like table_name;

执行optimize操作后
-- 整理空间碎片optimize table test_myisam;

data_free选项代表数据碎片。
针对MySQL的不同数据库存储引擎,在optimize使用清除碎片,回收闲置的数据库空间,把分散存储的数据和索引重新挪到一起,对I/O速度有好处。
当然optimize在对表进行操作的时候,会加锁,所以不宜经常在程序中调用。
MyISAM存储引擎
可以直接使用该命令
InnoDB存储引擎
InnoDB引擎的表分为独享表空间和同享表空间的表,默认开启
show variables like 'innodb_file_per_table';

此时是无法对表进行optimize操作的,如果操作,会返回如图信息。

因为该结构下删除了大量的行,此时索引会重组并且会释放相应的空间因此不必优化
参考:
https://blog.csdn.net/hsd2012/article/details/51485250
https://zhuanlan.zhihu.com/p/98818611
https://www.cnblogs.com/ZhuChangwu/p/14041410.html#1896639506




