如何通过查询InformationSchema表了解MySQL中特定表的磁盘使用量?

2026-04-30 13:502阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计839个文字,预计阅读时间需要4分钟。

如何通过查询InformationSchema表了解MySQL中特定表的磁盘使用量?

MySQL 没有直接的 `SHOW TABLE SIZE` 命令,实际有效的办法只有查询 `INFORMATION_SCHEMA.TABLES`。这里,`DATA_LENGTH` 和 `INDEX_LENGTH` 字段加起来即为该表实际占用的磁盘字节数(不含碎片、undo log、binlog)。

注意:这个视图的数据是「采样值」,不是实时精确值——InnoDB 会定期更新统计信息,所以刚删完大量数据后,数值可能滞后几分钟。如果要强制刷新,可执行 ANALYZE TABLE table_name

DATA_LENGTHINDEX_LENGTH 分别代表什么

DATA_LENGTH 是表数据页(B+树叶子节点)占用的字节数;INDEX_LENGTH 是所有二级索引(非聚簇索引)页的字节数。主键索引已计入 DATA_LENGTH(因为 InnoDB 聚簇表数据即主键)。

  • 对 MyISAM 表,DATA_LENGTH 对应 .MYD 文件大小,INDEX_LENGTH 对应 .MYI 文件大小
  • 对 InnoDB 表,这两个值都来自 ibdata1 或独立表空间(.ibd),但不等于文件系统里 .ibd 的大小——因为包含空闲页、未 purge 的旧版本等
  • 如果启用了 innodb_file_per_table=OFF,所有表共享系统表空间,这时 TABLE_SCHEMAmysqlinformation_schema 的表也会显示非零值,但不能直接映射到单个文件

常用查询语句及注意事项

查当前库所有表容量(按大小倒序):

SELECT TABLE_NAME, ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS size_mb, ROUND(DATA_LENGTH / 1024 / 1024, 2) AS data_mb, ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS index_mb FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC;

关键点:

  • 务必加上 WHERE TABLE_SCHEMA = DATABASE(),否则会扫全实例所有库,慢且权限可能不足
  • 避免用 WHERE TABLE_SCHEMA = 'xxx' 硬编码,容易拼错库名或忽略大小写(Linux 下库名区分大小写)
  • 不要用 ROUND(... / 1024 / 1024 / 1024, 2) 算 GB——小表会显示 0.00,掩盖真实差异;先按 MB 看,再挑大的单独算 GB
  • 如果某张表 DATA_LENGTH = 0 但行数不为 0,大概率是表被 TRUNCATE 过但统计未更新,执行 ANALYZE TABLE 即可

为什么 du -sh *.ibd 和查询结果不一致

文件系统命令看到的是 .ibd 文件大小,而 INFORMATION_SCHEMA.TABLES 显示的是「已分配并使用的页空间」。两者差值常见于:

  • InnoDB 启动时预分配空间(尤其 innodb_autoextend_increment 较大时)
  • 删除大量行后,空间未立即回收给操作系统(需 OPTIMIZE TABLEALTER TABLE ... ENGINE=InnoDB
  • 存在未 purge 的历史版本(长事务、高 innodb_max_purge_lag
  • 加密表或压缩表(ROW_FORMAT=COMPRESSED)中,DATA_LENGTH 是解压后逻辑大小,du 是压缩后物理大小

线上排查磁盘爆满时,优先信 du;判断「哪些表真正在吃空间」,优先信 INFORMATION_SCHEMA 的聚合值。

标签:Mysql

本文共计839个文字,预计阅读时间需要4分钟。

如何通过查询InformationSchema表了解MySQL中特定表的磁盘使用量?

MySQL 没有直接的 `SHOW TABLE SIZE` 命令,实际有效的办法只有查询 `INFORMATION_SCHEMA.TABLES`。这里,`DATA_LENGTH` 和 `INDEX_LENGTH` 字段加起来即为该表实际占用的磁盘字节数(不含碎片、undo log、binlog)。

注意:这个视图的数据是「采样值」,不是实时精确值——InnoDB 会定期更新统计信息,所以刚删完大量数据后,数值可能滞后几分钟。如果要强制刷新,可执行 ANALYZE TABLE table_name

DATA_LENGTHINDEX_LENGTH 分别代表什么

DATA_LENGTH 是表数据页(B+树叶子节点)占用的字节数;INDEX_LENGTH 是所有二级索引(非聚簇索引)页的字节数。主键索引已计入 DATA_LENGTH(因为 InnoDB 聚簇表数据即主键)。

  • 对 MyISAM 表,DATA_LENGTH 对应 .MYD 文件大小,INDEX_LENGTH 对应 .MYI 文件大小
  • 对 InnoDB 表,这两个值都来自 ibdata1 或独立表空间(.ibd),但不等于文件系统里 .ibd 的大小——因为包含空闲页、未 purge 的旧版本等
  • 如果启用了 innodb_file_per_table=OFF,所有表共享系统表空间,这时 TABLE_SCHEMAmysqlinformation_schema 的表也会显示非零值,但不能直接映射到单个文件

常用查询语句及注意事项

查当前库所有表容量(按大小倒序):

SELECT TABLE_NAME, ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS size_mb, ROUND(DATA_LENGTH / 1024 / 1024, 2) AS data_mb, ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS index_mb FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC;

关键点:

  • 务必加上 WHERE TABLE_SCHEMA = DATABASE(),否则会扫全实例所有库,慢且权限可能不足
  • 避免用 WHERE TABLE_SCHEMA = 'xxx' 硬编码,容易拼错库名或忽略大小写(Linux 下库名区分大小写)
  • 不要用 ROUND(... / 1024 / 1024 / 1024, 2) 算 GB——小表会显示 0.00,掩盖真实差异;先按 MB 看,再挑大的单独算 GB
  • 如果某张表 DATA_LENGTH = 0 但行数不为 0,大概率是表被 TRUNCATE 过但统计未更新,执行 ANALYZE TABLE 即可

为什么 du -sh *.ibd 和查询结果不一致

文件系统命令看到的是 .ibd 文件大小,而 INFORMATION_SCHEMA.TABLES 显示的是「已分配并使用的页空间」。两者差值常见于:

  • InnoDB 启动时预分配空间(尤其 innodb_autoextend_increment 较大时)
  • 删除大量行后,空间未立即回收给操作系统(需 OPTIMIZE TABLEALTER TABLE ... ENGINE=InnoDB
  • 存在未 purge 的历史版本(长事务、高 innodb_max_purge_lag
  • 加密表或压缩表(ROW_FORMAT=COMPRESSED)中,DATA_LENGTH 是解压后逻辑大小,du 是压缩后物理大小

线上排查磁盘爆满时,优先信 du;判断「哪些表真正在吃空间」,优先信 INFORMATION_SCHEMA 的聚合值。

标签:Mysql