最快方式是查 information_schema.tables 获取 innodb 表行数估算值,其 table_rows 字段为采样结果(误差10%~20%),myisam 为精确值;需精确值时须逐表执行 select count(*),无法单条 sql 原子化完成。

直接查 information_schema.tables 是最快方式
MySQL 本身不缓存每个表的实时行数,但 information_schema.tables 中的 table_rows 字段提供了 InnoDB 表的**估算值**(MyISAM 是精确值)。对大多数监控、统计类场景已足够快且够用。
执行这条语句就能拿到当前数据库所有表的记录数估算:
SELECT table_name, table_rows FROM information_schema.tables WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE';
-
table_schema = DATABASE()确保只查当前选中的库,别硬写库名,避免跨库误查 - InnoDB 的
table_rows是采样估算,误差可能达 10%~20%,不能用于数据校验或事务一致性判断 - 如果需要精确值,必须对每张表执行
SELECT COUNT(*),但大表会锁表或严重拖慢查询
需要精确总数时,SELECT COUNT(*) 必须逐表执行
没有单条 SQL 能原子化地对所有表执行 COUNT(*) 并聚合结果——MySQL 不支持动态表名拼接后直接执行(EXECUTE 需要 PREPARE,且无法返回多结果集到客户端)。
最实用的做法是生成一批 COUNT 语句再批量执行:
SELECT CONCAT('SELECT ''', table_name, ''' AS table_name, COUNT(*) AS row_count FROM `', table_name, '`;')
FROM information_schema.tables
WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE';
复制输出结果,粘贴进客户端执行。注意:
- 包含反引号
`是为了兼容含特殊字符或关键字的表名(如`order`) - 如果某张表没主键或没索引,
COUNT(*)可能全表扫描,耗时陡增;可先用EXPLAIN看执行计划 - 不要在业务高峰期跑这个,尤其对千万级以上表
SHOW TABLE STATUS 和 information_schema 数据来源一致
SHOW TABLE STATUS LIKE '%' 返回的 Rows 列,底层就是读的 information_schema.tables,两者数值完全相同,只是展示格式不同。
它适合快速人工查看,但不适合程序解析:字段顺序不固定、有额外元信息(如 Engine, Data_length),且无法用 WHERE 过滤库名。
- 想脚本化处理,坚持用
information_schema.tables,字段明确、可过滤、可 JOIN -
SHOW TABLE STATUS在某些低版本 MySQL(如 5.6)中对临时表或分区表可能返回NULL的Rows
分区表或大宽表要注意 table_rows 明显不准
当表开启分区(PARTITION),或者存在大量未清理的删除间隙(比如频繁 DELETE 后没做 OPTIMIZE TABLE),table_rows 估算偏差会更大,甚至显示为 0 或远低于实际。
- 确认是否分区:查
information_schema.partitions,看table_name对应的partition_name是否非空 - InnoDB 表长期运行后,可通过
ANALYZE TABLE table_name主动更新统计信息,让table_rows更接近真实 - 如果业务要求精确,且表不大(COUNT(*);否则得接受估算,并在文档里注明“非精确统计”
table_rows 的估算性质,或者试图用一条 SQL 解决本需分步处理的问题。查总数这件事,本质是在「快」和「准」之间做取舍,选哪边,得看你的下游系统能不能容忍误差。











