information_schema.tables可查表空间但data_length和index_length常不准,因受引擎类型、统计滞后、null值、分区表及视图影响;应结合analyze table、coalesce、文件系统命令(如du)综合验证。

查 information_schema.TABLES 是对的,但别直接信 data_length 和 index_length
MySQL 的 information_schema.TABLES 确实是查表空间的入口,但它的字段值受存储引擎、统计信息更新频率、是否启用 innodb_stats_persistent 等影响,常有滞后或偏差。尤其是 MyISAM 表的 data_length 通常准,InnoDB 表则容易低估(比如没算未 purge 的旧版本页)或高估(比如包含大量空闲页)。
实操建议:
- 先确认引擎:
SHOW CREATE TABLE `your_table`;—— 不同引擎查法和解读逻辑不同 - 强制刷新统计(仅 InnoDB):
ANALYZE TABLE `your_table`;,再查TABLES,否则可能用的是过期采样值 - 注意库名大小写:查询时
table_schema必须严格匹配实际库名(Linux 下区分大小写) - 避免用
SELECT *查TABLES,只取关键字段:table_name、engine、data_length、index_length、table_rows
用 SELECT SUM(data_length + index_length) 汇总单库空间要小心 NULL 和分区表
很多人想算整个库占多少空间,习惯写 SELECT SUM(data_length + index_length) FROM information_schema.TABLES WHERE table_schema = 'db_name',结果为 NULL 或明显偏小。
常见原因:
-
data_length或index_length任一为NULL,加法结果就是NULL—— 必须用COALESCE:SUM(COALESCE(data_length,0) + COALESCE(index_length,0)) - 分区表(PARTITIONED)在
TABLES中只有一行主记录,但真实数据分散在多个分区文件里,data_length可能只反映元数据,不反映实际磁盘占用 - 如果库下有视图(VIEW),它也会出现在
TABLES中,但engine是NULL,data_length也是NULL,不加过滤会干扰求和
真正落地看磁盘占用,得绕开 information_schema 直接看文件系统
当你要验证「这表到底占了多少 GB」,尤其涉及归档、删除后空间是否回收、或怀疑 ibdata1 膨胀时,information_schema 就不够用了。
实操路径:
- InnoDB 共享表空间(
innodb_file_per_table=OFF):所有表数据都在ibdata1,无法按表分离 —— 此时查information_schema的data_length完全无意义,只能看ls -lh /var/lib/mysql/ibdata1 - InnoDB 独立表空间(默认 ON):对应
.ibd文件在/var/lib/mysql/your_db/your_table.ibd,du -h最准:du -h /var/lib/mysql/your_db/your_table.ibd - MyISAM 表:查
.MYD(数据)和.MYI(索引)两个文件:du -ch /var/lib/mysql/your_db/your_table.{MYD,MYI} - 注意权限:MySQL 进程用户(如
mysql)才有权读这些文件;用 root 查时,确保没被 SELinux 或 AppArmor 拦截
information_schema 查询慢?不是表大,是元数据锁或统计线程卡住
执行 SELECT * FROM information_schema.TABLES WHERE table_schema = 'xxx' 卡住几秒甚至几十秒,不是因为表多,而是 MySQL 在构造这张虚拟表时要采集实时统计,可能触发元数据锁(MDL)或等待 INFORMATION_SCHEMA 内部缓存刷新。
提速办法:
- 加
WHERE engine IS NOT NULL过滤掉视图和临时表,减少扫描范围 - 避免在业务高峰查全库
TABLES,改用按表名精确查询:WHERE table_schema = 'db' AND table_name = 't' - 如果只是想比大小,用
ORDER BY data_length + index_length DESC LIMIT 10,别全扫 - 极端情况可关掉动态统计(不推荐):
SET SESSION innodb_stats_on_metadata = OFF,但会影响后续执行计划
查磁盘空间这事,表面是 SQL 查询,实际牵扯引擎机制、文件系统权限、统计策略三层。最易被忽略的是:你看到的数字到底是“逻辑大小”“分配大小”还是“物理占用”,三者差一个 OPTIMIZE TABLE 或一次大事务就能差出好几个 GB。











