### 15.11.4 对表进行碎片整理

[](<>)[](<>)

对二级索引的随机插入或删除可能会导致索引变得碎片化。碎片化是指磁盘上索引页的物理顺序与页上记录的索引顺序不接近，或者在分配给索引的 64 页块中有许多未使用的页。

碎片化的一个症状是表占用的空间超过了它“应该”占用的空间。究竟是多少，很难确定。全部`InnoDB`数据和索引存储在[B树](glossary.html#glos_b_tree), 和他们的[填充因子](glossary.html#glos_fill_factor)可能从 50% 到 100% 不等。碎片的另一个症状是像这样的表扫描花费的时间比它“应该”花费的时间更多：

```
SELECT COUNT(*) FROM t WHERE non_indexed_column <> 12345;
```

前面的查询需要 MySQL 执行全表扫描，这是对大表最慢的查询类型。

为了加快索引扫描，您可以定期执行“null”[`更改表`](alter-table.html)操作，这会导致 MySQL 重建表：

```
ALTER TABLE tbl_name ENGINE=INNODB
```

你也可以使用[`更改表 *`tbl_name`* 力量`](alter-table.html)执行重建表的“空”改变操作。

两个都[`更改表 *`tbl_name`* 引擎=INNODB`](alter-table.html)和[`更改表 *`tbl_name`* 力量`](alter-table.html)采用[在线 DDL](innodb-online-ddl.html).有关详细信息，请参阅[第 15.12 节，“InnoDB 和在线 DDL”](innodb-online-ddl.html).

执行碎片整理操作的另一种方法是使用[**mysql转储**](mysqldump.html)将表转储到文本文件，删除表，然后从转储文件重新加载。

如果对索引的插入始终是升序的，并且只从末尾删除记录，则`InnoDB`文件空间管理算法保证索引中不会出现碎片。
