information_schema.tables 是唯一能查各表逻辑空间的入口,其 data_length+index_length 为 innodb 页级估算值,非磁盘实时字节数;查指定库需过滤 table_schema、table_type='base table' 且 engine is not null,结果按总大小倒序排列。

information_schema.TABLES 是唯一能查到数据库中各表逻辑空间的入口,但它的值是 InnoDB 页级估算值,不是磁盘上实时字节数——日常分析够用,但别拿它和 du 对比找“误差”。
查指定库所有表的大小(含数据+索引)
核心就是过滤 TABLE_SCHEMA,并用 DATA_LENGTH + INDEX_LENGTH 算总空间。必须加 TABLE_TYPE = 'BASE TABLE' 和 ENGINE IS NOT NULL,否则会混入视图、系统表或 MEMORY 表(它们的 DATA_LENGTH 恒为 0,拉低统计):
SELECT TABLE_NAME AS `table`, 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`, TABLE_ROWS AS `rows` FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db_name' AND TABLE_TYPE = 'BASE TABLE' AND ENGINE IS NOT NULL ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC;
- 替换
'your_db_name'为实际数据库名,别漏单引号 -
TABLE_ROWS对 InnoDB 是估算值,删过大量数据后可能不准 - 结果按总大小倒序,一眼看出谁占得最多
为什么不能直接用 SHOW TABLE STATUS
SHOW TABLE STATUS 返回的 Data_length 和 Index_length 字段看起来一样,但它不支持 WHERE 过滤库名,也没法 ORDER BY 聚合——你只能手动翻页找,没法排序或导出。更关键的是,它的字段值来源不稳定:在某些 MySQL 版本里,它可能返回缓存旧值,而 information_schema.TABLES 是每次查询都走引擎元数据接口,一致性更高。
查单表详细空间时容易漏的关键条件
只查一张表?别只加 table_name,还得保留 TABLE_SCHEMA 和 ENGINE IS NOT NULL:
SELECT TABLE_NAME, ENGINE, ROUND(DATA_LENGTH / 1024 / 1024, 2) AS `data_mb`, ROUND(INDEX_LENGTH / 1024 / 1024, 2) AS `index_mb`, ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024, 2) AS `total_mb` FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db_name' AND TABLE_NAME = 'your_table_name' AND ENGINE IS NOT NULL;
- 不加
ENGINE IS NOT NULL,万一这张表是MEMORY引擎,DATA_LENGTH就是 0,你会误判为空表 -
ENGINE字段能帮你快速确认是不是 InnoDB —— 只有 InnoDB 的DATA_LENGTH才和.ibd文件大小基本对应(当innodb_file_per_table=ON时) - 如果查不到结果,先检查用户是否有权限读取该库的
information_schema.TABLES(特别是 RDS 或权限收紧环境)
这个“大小”到底准不准?
它准在哪儿、不准在哪儿,得看存储引擎和配置:
- InnoDB 表且
innodb_file_per_table = ON(默认):DATA_LENGTH + INDEX_LENGTH和ls -lh table_name.ibd结果基本一致,误差在 16KB(一页)以内 - InnoDB 表但
innodb_file_per_table = OFF:所有表共享ibdata1,这里查出来的只是逻辑估算,物理文件根本没法按表拆分 - MyISAM 表:
DATA_LENGTH更接近真实.MYD文件大小,但依然不含.MYI的部分开销 - 大量
DELETE后没OPTIMIZE TABLE:DATA_LENGTH可能已缩小,但磁盘空间不会自动还给系统——这时查出来“小”,du看着还是“大”
真要确认磁盘用了多少,必须登服务器跑 du -sh /var/lib/mysql/your_db_name/*.ibd(InnoDB)或 *.MYD(MyISAM)——SQL 层永远只告诉你“它认为自己用了多少”。











