最准的是count()但有锁表风险,information_schema.tables.table_rows对innodb仅是估算值(误差常达10%~50%),myisam才准确;日常用前者粗略判断,精确统计须用count()并避开高峰、优先查从库。

直接查 information_schema.tables.table_rows 是最快的方式,但它给的是估算值,不是精确值——这点必须前置确认,否则后续逻辑会出错。
为什么 table_rows 不准但还能用
MySQL 对 InnoDB 表的 table_rows 值来自采样分析(ANALYZE TABLE 触发),不随每次增删实时更新。它反映的是“某个快照时刻的统计估算”,误差常在 10%~50%,尤其在刚大批 INSERT 或 DELETE 后更离谱。
- 该值对 MyISAM 是精确的,但 MyISAM 已基本淘汰,不用考虑
- 即使刚手动执行过
ANALYZE TABLE t,当前事务中看到的仍可能是旧 MVCC 快照,不是最新估算 - 适合场景:运维巡检、容量趋势判断、分页总数展示(允许跳页)、告警阈值粗判
- 不适合场景:数据迁移校验、空表判定(
table_rows IS NULL在低版本如 5.6 中常见)、业务分支逻辑(如“若为空则初始化”)
怎么安全地查 table_rows
必须加过滤,否则可能锁住元数据或拖慢整个实例:
- 写死库名:
WHERE table_schema = 'your_db',绝不能省略 - 限定表类型:
AND table_type = 'BASE TABLE',排除视图干扰 - 空值兜底:
IFNULL(table_rows, 0),避免 5.6 等旧版本返回 NULL 导致应用报错 - 示例语句:
SELECT table_name, IFNULL(table_rows, 0) AS rows FROM information_schema.tables WHERE table_schema = 'myapp' AND table_type = 'BASE TABLE' ORDER BY rows DESC;
SHOW TABLE STATUS 和 EXPLAIN 的 rows 值区别
三者都不可信,但来源和用途不同:
-
SHOW TABLE STATUS LIKE 't'返回的Rows列 =information_schema.tables.table_rows,同源,同误差 -
EXPLAIN SELECT COUNT(*) FROM t中的rows是优化器对“本次查询将扫描多少行”的预估,基于索引统计+采样,和真实行数无关;它甚至可能为 1(误判走索引覆盖)或远超实际值(统计过期) - 二者都不能用于需要确定性的场合,但
SHOW TABLE STATUS多带了Data_length和Index_length,更适合看存储膨胀趋势(比如table_rows没变但Data_length翻倍,大概率有大量软删除未 purge)
真正难的不是查哪个字段,而是想清楚你要这个数字干什么——如果业务能接受 ±30% 误差,table_rows 就是唯一实用入口;一旦要求精确,就得直面 COUNT(*) 的 O(n) 本质,再快的“技巧”也绕不开可见性判断这一步。











