将 TEXT 值设置为 null 不会减少磁盘 space 对 MySQL table 的使用

Setting TEXT values to null does not reduce disk space usage of MySQL table

我正在尝试减少 MySQL 5.6.23 的 RDS 实例中 table 的磁盘 space 使用率。这是一个 InnoDB table,大约有 800 万行和 30 列。一些列的类型为 TEXT NULL DEFAULT NULL。 table 如此大的原因之一是因为不是从 table 中删除行,而是通过名为 'deleted' 的标志列将它们标记为已删除。

阅读有关存储要求的 MySQL 文档后:

http://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html

似乎 TEXT 字段所需的存储空间取决于字段中文本的长度,而不是固定大小 (L + 2 bytes, where L < 2^16 and where L is the length of the value in bytes)。因此,尽管我在其他地方读到这些字段实际上是固定宽度的,但我处理了大约 50,000 行标记为已删除并将它们的所有 TEXT 列值设置为空。

但是,MySQL 客户端或 AWS 控制台 RDS 界面报告的磁盘 space 没有减少。为什么这没有释放磁盘 space?

当您将列值设置为 NULL 时,InnoDB 将不得不重新组织记录存储以减少 table 使用的磁盘总量 space。如果你的虚拟 ALTER TABLE 不足以让 MySQL 注意到短路的方式,你应该会看到一个减少,它实际上重建了 table,或者手动删除,重新创建并重新插入记录。 OPTIMIZE TABLE 也应该这样做。

Sasha 的回答可能适用也可能不适用。

将列设置为 NULL 后,任何释放的块都可用于将来 INSERTs / UPDATEs。但是释放的块不会返回给 OS。一个块是否被释放取决于很多细节。

TEXT 字段的磁盘数量 space 取决于文本数量和 Row_format("Compact",等等)。 TEXT 列可以全部或部分存储在与其余数据分开的块中。

如果您的 table 是在 innodb_file_per_tableON 时创建的,那么 OPTIMIZE TABLE 会将免费的 space 还给 OS .并且 SHOW TABLE STATUS 将显示值有所下降。

如果 innodb_file_per_tableOFF,释放的 space 留在 ibdata1 中,但该文件没有缩小。只有dump all tables才能缩水;停止 mysqld;删除 ibdata1;重新开始;重新加载。 (讨厌。)OPTIMIZE TABLE 将在 ibdata1.

内增加 Data_free

(假设关闭)这将使 table 更易于管理,但在未缩小的 ibdata1:

中留下大量空闲 space
SET innodb_file_per_table = ON;
ALTER TABLE foo ENGINE=InnoDB;

如果您预计 ibdata1 因其他原因而增长;这可能是明智之举。否则,它只会使磁盘 space 问题变得更糟。