对二级索引的随机插入和删除会导致索引碎片化。碎片化意味着磁盘上索引页面的物理顺序和页面上索引记录的顺序距离较远,或者说被分配给索引的64页的区块中有很多未使用的页。
碎片化的一个标志之一是表占用的空间比它 “应该”占用的大。具体多少很难确定。所有的InnoDB数据和索引都存储在B+树中,它们的填充因子可能会从50%到100%之间变化。另外一个碎片化的症状是扫描表时耗费的时间比它“应该”花费的时间更长:
SELECT COUNT(*) FROM t WHERE non_indexed_column <> 12345;
上面的这个语句需要MySQL执行全表扫描,这是查询一张大表时最慢的一种方式。
想要加速索引扫描,你可以定期执行“空” ALTER TABLE操作,这会导致MySQL重建整整表:
ALTER TABLE tbl_name ENGINE=INNODB
你也可以使用ALTER TABLE tbl_name FORCE来执行重建表的“空” alter操作。
这两种操作都使用online DDL。想了解更多信息,请查阅15.12,“InnoDB和Online DDL”;
另外一个整理表的操作是使用mysqldump来将表dump到一个文本文件中,删除这张表,然后加载这个文本文件。
如果插入索引时总是正向的,而删除时总是从尾部开始删除,InnoDB空间管理算法会保证不会发生碎片化。