mysql - 解读mysql的information_schema.tables DATA_LENGTH, INDEX_DATA_LENGTH and DATA_FREE

标签 mysql

我希望有人能解释为什么两个小时的数据清除据称会导致我的 mysql 实例上的数据使用量仅减少 32 KB。这是我的详细信息:

我有一个 mysql 数据库(在 Amazon RDS 上运行),我正试图从中清除数据。我这样做是为了避免存储空间用完,因为亚马逊将您的存储空间限制在 1TB,如果我们不采取任何行动,我们最终会达到这个限制。

我正在使用这个命令来计算我的表和索引的大小:

select * from information_schema.tables;

特别是有两个 InnoDB 表占用了我的大部分存储空间。我有一个循环遍历我最大的表删除记录的过程。在时间 t = 0 时,我运行了上面的 SQL 查询并得到了数据长度和索引数据长度的以下结果:

  • 数据长度:56431116288
  • 索引数据长度:74233151488

两个小时后,在连续运行我的数据库清理程序后,我运行了上面的 SQL 语句并得到以下结果:

  • 数据长度:56431083520
  • 索引数据长度:74126147584

这基本上意味着我削减了 32 KB 的表数据和 102 MB 的索引数据。

索引的减少是有道理的。表数据的减少非常小。在此期间不可能插入其他数据,因为我正在我的数据库的备份副本上运行此测试(RDS 的好处之一是您可以启动并运行数据库的完整副本以运行实验上,比如这个)。我还确认 AUTO_INCREMENT 值两次都相同。

有人可以解释为什么数据长度根本没有移动多少吗?数据长度只是一个非常快速和肮脏的近似值吗? mysql 最终会执行其他压缩步骤吗?还是我完全误解了这些字段的用法?

谢谢!

更新

我可能已经想通了——在时间 t=0

  • DATA_FREE = 77594624

四个小时后,

  • DATA_FREE = 256901120

这意味着我将 DATA_FREE 增加了大约 171MB。

这是否意味着如果我再插入 171MB,它将从 DATA_FREE 池中取出,因此我的数据长度不会增加?

换句话说,假设我从一个新的 InnoDB 表开始并插入 20 GB 的数据(假设 20 GB 合并了所有多余的 InnoDB 数据,我意识到 InnoDB 中存储的数据比 MyISAM 大),然后我删除所有数据,然后我插入 10 GB 的数据。当我运行 select * from information_schema.tables 时,我应该会看到 Data length of 10 GB 和 Data free of 10 GB,对吧?我不应该期望看到 30 GB 的数据长度/0 GB 的免费数据,也不应该期望看到 10 GB 的数据长度/10 GB 的免费数据?

更新 2

This post on Stack Overflow似乎也证实了我的分析。

最佳答案

表的“数据长度”包括表中可能存在的任何空闲空间。您可能需要OPTIMIZE 对表进行碎片整理,释放该空间。请注意,这可能会在执行操作时将表锁定一段时间。

使用 InnoDB 存储引擎 (CREATE TABLE ( ... ) ENGINE=InnoDB;) 将使表优化在很大程度上变得不必要,并使数据库通常更快。如果您还没有使用它,您应该开始。 :)

关于mysql - 解读mysql的information_schema.tables DATA_LENGTH, INDEX_DATA_LENGTH and DATA_FREE,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8004971/

相关文章:

MySQL基于月份跨度的选择查询

mysql - 如何使用具有多个条件的左连接来连接两个表?

mysql - 无法设置MySQL查询缓存

php - 复选框值到mysql查询

mysql - 如何远程连接MySQL数据库服务器?

mysql - 数据库设计,如何设置表

mysql - @Get Controller 和 bool 查询内的 NestJS 验证失败(需要数字字符串)

mysql - 在 mysql 语句中使用 For 循环在 vb.net 中变慢

java - MySQL Workbench 和 JDBC 中的 utf8mb4

mysql - 如何在 django 中向大文本字段添加唯一约束?