information_schema.tables 的 data_length 和 index_length 是估算值,尤其 innodb 表未 analyze 或 innodb_stats_persistent=off 时误差大;真实磁盘大小需查 .ibd 文件。

查 information_schema.tables 时为什么结果不准
直接查 information_schema.tables 得到的 data_length 和 index_length 是估算值,尤其在 InnoDB 表没做 ANALYZE TABLE 或者启用了 innodb_stats_persistent = OFF 时,可能和实际磁盘占用差几倍。MySQL 不会实时统计,而是按采样估算。
- MyISAM 表的大小字段基本准,InnoDB 则大概率不准
- 如果刚删了大量数据但没执行
OPTIMIZE TABLE,data_length还是旧的高位值 -
information_schema默认只显示当前用户有权限的库,跨库查不到,得用SELECT ... FROM information_schema.tables WHERE table_schema = 'xxx'显式指定
真正靠谱的查法:用 DATA_LENGTH + INDEX_LENGTH 加排序
虽然不准,但相对排序一般没问题——最大的表通常还是排第一。关键是要过滤掉视图、系统库,并把单位统一成 MB 方便比较。
- 必须加
WHERE engine IS NOT NULL,否则视图(ENGINE = NULL)会混进来,导致NULL + NULL计算出错 - 用
ROUND((data_length + index_length) / 1024 / 1024, 2)转成 MB,避免数字太长看花眼 - 加上
ORDER BY data_length + index_length DESC LIMIT 10看前 10 大,别只取 1 个——有时日志表或备份表意外顶上来了
SELECT
table_schema,
table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
AND engine IS NOT NULL
ORDER BY data_length + index_length DESC
LIMIT 10;
想看真实磁盘占用?得去文件系统里看
MySQL 层面的数据长度不等于磁盘上 .ibd 文件大小,尤其是开了压缩、页大小非默认、或者有大量未清理的 undo log 时。
- 先查表对应的文件路径:
SELECT file_path FROM performance_schema.data_locks不行,得用SHOW CREATE TABLE db.tbl看DATA DIRECTORY,或默认在datadir下的db_name/tbl_name.ibd - 登录服务器后用
du -sh /var/lib/mysql/db_name/*.ibd,注意区分独立表空间(innodb_file_per_table = ON)和系统表空间 - 如果表特别大(比如 >50GB),
du可能卡住,改用ls -lh看大小更轻量
information_schema.tables 查询慢怎么办
库里表一多(比如几千张),查 information_schema.tables 会明显变慢,因为 MySQL 要遍历每个表收集元数据。
- 加
WHERE table_schema = 'your_db'限定库,别扫全库 - 避免在应用里高频轮询这个视图,它不是为高并发设计的
- 如果只是定期巡检,可以建一张本地汇总表,每天凌晨用事件(
EVENT)跑一次写入,查这张表更快 -
SELECT COUNT(*) FROM information_schema.tables这种也慢,同理要加WHERE











