我们都知道,在mysql (这里只探讨innodb) 中delete数据,并非真实删除,而是在这行数据上打了一个del的标记,所以这行占用的空间也并不会释放,但是空间可以被复用,所以期望用delete数据来释放空间的同学可以醒醒了。这样就造成了空间上的碎片,那么如果干掉这些碎片呢。
这里先说结论,alter table语句可以触发表重建,消除碎片空间。
mysql中的数据存储结构大概是下面这个样子的
变长字段长度:82 80 10 08
Null值列:00
头信息:00 00 30 01 04
隐藏列DB_ROW_ID:00 00 00 00 00 0c
隐藏列DB_TRX_ID:00 00 00 03 c9 6e
隐藏列DB_ROLL_PTR:40 00 00 01 89 1c 51
列数据id(1):00 00 00 00 00 00 00 01
...
而delete掉的标记会记录在头信息中。
做个实验,看看空间是否真的没有释放;
创建一张表user,并插入很多数据
create table test.userc(
id int unsigned auto_increment, name varchar(128) not null default '',
age int unsigned not null default 0,
key id(id)
);
insert into userc(name, age) value ("张三",10),("张三",10),........
查看表的文件大小
-rw-r----- 1 root admin 256K 6 1 16:54 userc.ibd
再随便插入几条
-rw-r----- 1 root admin 272K 6 1 16:55 userc.ibd
ok这里看到文件大小增加了16k,这是因为mysql的一页就是16k,所以文件大小是16k、16k的增长的。
这时候我们删除大量的数据再次查看文件大小,仍然是272k,索命,数据虽然删除,但是空间没有释放。
-rw-r----- 1 root admin 272K 6 1 16:55 userc.ibd
这里我们对主键执行一个alter table语句
alter table test.userc modify column id bigint unsigned not null auto_increment;
再次查看文件大小
-rw-r----- 1 root admin 164K 6 1 16:57 userc.ibd
ok 文件大小明显的减少,这里说明主键的alter语句会重建表,并且释放碎片空间;
这时候我们再删除大量的数据再次查看文件大小,这里我们对普通列执行一个alter table语句
alter table test.userc modify column name varchar(20) not null default '';
再次查看文件大小
-rw-r----- 1 root admin 128K 6 1 16:59 userc.ibd
ok 文件大小明显的减少,这里说明普通列的alter语句会重建表,并且释放碎片空间;