查大表必须加 where engine is not null,否则 information_schema.tables 会包含视图(data_length 和 index_length 为 null),导致 order by data_length + index_length 排序失效;正确写法是 where table_schema = database() and engine is not null,并用 order by (data_length + index_length) desc limit 10。

查大表必须加 WHERE engine IS NOT NULL
不加这个条件,INFORMATION_SCHEMA.TABLES 会把视图(VIEW)也拉进来,而视图的 DATA_LENGTH 和 INDEX_LENGTH 都是 NULL。一旦参与 ORDER BY data_length + index_length,整行排序就失效——MySQL 对含 NULL 的算术表达式默认排最前或最末,结果不可靠,甚至可能漏掉真正的大表。
正确做法是显式过滤掉非引擎表:
WHERE table_schema = 'your_db' AND engine IS NOT NULL- 如果只关心当前库,用
WHERE table_schema = DATABASE()更安全,避免手误输错库名 - 别用
SHOW TABLE STATUS替代——它不保证返回所有表,且在某些 MySQL 版本里对大库响应极慢
DATA_LENGTH + INDEX_LENGTH 是实际磁盘占用的合理近似
这个和不是“精确大小”,但足够用于排序和识别大表:DATA_LENGTH 是数据页占用字节数,INDEX_LENGTH 是索引页字节数,两者相加基本反映该表在磁盘上的真实开销(不含 .frm 或 .ibd 文件头等微量元数据)。
注意几个常见偏差点:
- MyISAM 表的
DATA_LENGTH包含删除标记但未回收的空间,所以比SELECT COUNT(*)推算的略大 - InnoDB 表的值受
innodb_file_per_table影响:关闭时所有表共享 ibdata1,此时DATA_LENGTH仍能反映逻辑大小,但物理文件无法单独清理 - 刚执行过
OPTIMIZE TABLE的表,值会明显下降;刚大批量插入后没做统计更新,值可能滞后(需ANALYZE TABLE)
单位换算和排序写法要防溢出、易读、留余量
直接用字节排序数字太长,人眼难判断;全用 ROUND(..., 2) 又可能让多个小表显示为 0.00 MB 而丢失区分度。
推荐组合写法:
- 排序依据用原始字节数:
ORDER BY (data_length + index_length) DESC(避免浮点计算干扰排序稳定性) - 显示列转 MB 时用
ROUND((data_length + index_length) / 1024 / 1024, 2),除法顺序不能颠倒(防止整数溢出) -
永远加
LIMIT 10,别只取LIMIT 1—— 日志表、历史备份表、临时中间表常意外冲到第一,看前十才能判断是否异常
典型可直接执行的语句:
SELECT table_name,
ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb,
table_rows
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND engine IS NOT NULL
ORDER BY (data_length + index_length) DESC
LIMIT 10;
线上环境慎用 INFORMATION_SCHEMA 全库扫描
在几百个库、上万张表的实例中,SELECT ... FROM information_schema.TABLES 可能锁住元数据、拖慢其他 DDL 操作,尤其 MySQL 5.7 及更早版本。
应急时优先缩小范围:
- 先确认目标库:
SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME NOT IN ('mysql','information_schema','performance_schema','sys') - 再针对单库查表,比全实例扫快一个数量级
- 如发现某库特别慢,改用
SELECT name, n_rows, clustered_index_size, sum_of_other_index_sizes FROM mysql.innodb_table_stats WHERE database_name = 'xxx'(需有权限且 stats 已启用)
真正的大表问题往往藏在排序结果的第 3~7 名——第 1 名通常是预期中的订单或日志表,反而是后面那些“不该这么大”的表,比如未清理的调试临时表、失败任务残留的中间结果,最容易被忽略。











