MySQL COUNT
MySQL 统计表的行数有多少条,有几种方式?每天统计一次推荐用什么方式?
- InnoDB 不维护真实行数(只是近似值,COUNT(*) 会全表扫描)
- MyISAM 维护了行数(COUNT(*) 很快)
- 行数统计对大表可能非常慢,需要根据使用场景选择方案
SELECT COUNT(*) FROM user;
特点:
- 精确值
- 全表扫描(大表慢)
- InnoDB 会做行锁,可能影响并发
SELECT COUNT(id) FROM user;
特点:
- 对 NOT NULL 列,效果与 COUNT(*) 一样
- 对可 NULL 列,会忽略 NULL
- InnoDB 性能依然慢(全表扫描)
SELECT table_rows
FROM information_schema.tables
WHERE table_schema='test'
AND table_name='user';
特点:
- 非常快
- 只是估算值
- 适合大表做 每日统计 / 数据监控
- 每天执行一次足够
- 维护一个 行数统计表
- 每次 INSERT / DELETE / TRUNCATE 同步更新
- 适合大表 / OLAP 场景
示例:
CREATE TABLE table_count (
table_name VARCHAR(64) PRIMARY KEY,
row_count BIGINT
);
-- 每次增删同步更新
UPDATE table_count SET row_count = row_count + 1 WHERE table_name='user';
优点:
- 统计实时
- 无需全表扫描
缺点:
- 需在应用或触发器维护
- 容易出错(事务异常)
- ANALYZE TABLE user;
- 可获取 估算行数、索引分布、数据分布
- 可结合 EXPLAIN 做优化
- 大表推荐:INFORMATION_SCHEMA.tables.table_rows 或 业务累计表
- 中小表:COUNT(*) 精确统计没问题
- 报表 / OLAP:每天一次,增量更新到统计表,避免高峰期扫描
-
避免高峰期全表 COUNT
- 影响事务并发
-
统计表 + 触发器或应用逻辑更新
- 精准 + 高效
-
结合缓存(Redis / Memcached)
- 监控 / 频繁查询不 hit 数据库
-
使用近似算法
- HyperLogLog 等,用于大规模统计(百万级以上行)
Q1:InnoDB 为什么 COUNT(*) 慢?
因为 InnoDB 不维护真实行数,需要全表扫描。
Q2:信息模式的 table_rows 能用吗?
可以,但只估算,不精确。
Q3:如何每天统计大表行数?
使用 table_rows 估算 + 累计表 + 定时任务,避免高峰扫描。
Q4:为什么 MyISAM COUNT(*) 快?
MyISAM 记录了表行数,直接返回,不扫描数据。
| 场景 | 推荐方式 | 精确 | 性能 |
|---|---|---|---|
| 小表 / 不频繁 | COUNT(*) | ✅ | 可以接受 |
| 大表 / 日统计 | table_rows / 累计表 | ❌/✅ | 高 |
| OLAP / 日报 | 累计表 + 增量 | ✅ | 高 |
| 近似分析 | HyperLogLog | ❌ | 高 |