为什么表数据删掉一半,表文件大小不变?
表数据既可以存在共享表空间里,也可以是单独的文件。这个行为是由参数 innodb_file_per_table 控制的:
1. 这个参数设置为 OFF 表示的是,表的数据放在系统共享表空间,也就是跟数据字典放 在一起;
2. 这个参数设置为 ON 表示的是,每个 InnoDB 表数据存储在一个以 .ibd 为后缀的文件 中。
从 MySQL 5.6.6 版本开始,它的默认值就是 ON 了。
我建议你不论使用 MySQL 的哪个版本,都将这个值设置为 ON。因为,一个表单独存储 为一个文件更容易管理,而且在你不需要这个表的时候,通过 drop table 命令,系统就会 直接删除这个文件。而如果是放在共享表空间中,即使表删掉了,空间也是不会回收的。
所以,将 innodb_file_per_table 设置为 ON,是推荐做法,我们接下来的讨论都是基于 这个设置展开的。
我们在删除整个表的时候,可以使用 drop table 命令回收表空间。但是,我们遇到的更多 的删除数据的场景是删除某些行,这时就遇到了我们文章开头的问题:表中的数据被删除 了,但是表空间却没有被回收。
delete 命令其实只是把记录的位置,或者数据页标记为了“可复用”,但 磁盘文件的大小是不会变的。也就是说,通过 delete 命令是不能回收表空间的。这些可 以复用,而没有被使用的空间,看起来就像是“空洞”。
实际上,不止是删除数据会造成空洞,插入数据也会。 如果数据是按照索引递增顺序插入的,那么索引是紧凑的。但如果数据是随机插入的,就可能造成索引的数据页分裂。
另外,更新索引上的值,可以理解为删除一个旧的值,再插入一个新值。不难理解,这也 是会造成空洞的。
也就是说,经过大量增删改的表,都是可能是存在空洞的。所以,如果能够把这些空洞去 掉,就能达到收缩表空间的目的。
而重建表,就可以达到这样的目的。