COUNT(*)统计所有行(含NULL),性能最优;COUNT(col)仅统计非NULL值;GROUP BY需与SELECT字段匹配;INFORMATION_SCHEMA.TABLES提供近似行数和存储大小;COUNT(DISTINCT)易引发内存压力,高基数字段建议截取前缀或用索引基数估算。
直接查总数或按字段分组计数是最常见需求,COUNT() 是核心函数,但要注意它对 NULL 值的处理逻辑:默认忽略所有 NULL,所以 COUNT(col) 和 COUNT(*) 结果可能不同。
COUNT(*) 统计行数(包括含 NULL 的行),性能最优,MySQL 通常走索引行数估算(如 InnoDB 的元数据)COUNT(col) 只统计该列非 NULL 的值,若列无 NOT NULL 约束,结果可能少于总行数GROUP BY 时,记得在 SELECT 中只出现分组字段或聚合表达式,否则 MySQL 8.0+ 会报错 ERROR 1055
SELECT status, COUNT(*) AS cnt FROM orders GROUP BY status ORDER BY cnt DESC;
执行 SELECT COUNT(*) FROM table_name 在大表上可能慢且锁表,而 INFORMATION_SCHEMA.TABLES 提供的是近似行数(InnoDB 的估算值),但能秒出结果,适合快速巡检。
TABLE_ROWS 字段是 InnoDB 的采样估算,误差可能达 10%~20%,不能用于精确校验DATA_LENGTH 和 INDEX_LENGTH 单位是字节,可换算成 MB 判断是否异常膨胀TABLE_ROWS 对空表返回 NULL,需加 IFNULL 处理SELECT table_name, IFNULL(table_rows, 0) AS rows_est, ROUND((data_length + index_length) / 1024 / 1024, 2) AS size_mb FROM information_schema.tables WHERE table_schema = 'mydb' AND table_name = 'users';
查去重数量(如用户地域、设备类型)时,COUNT(DISTINCT col) 是标准写法,但要注意内存消耗——MySQL 会建临时哈希表,大表高基数字段易触发磁盘临时表甚至 OOM。
SHOW INDEX FROM table_name 查看 Cardinality(索引基数),它是采样估算,速度快但不精确GROUP BY + COUNT(*) 加 LIMIT 防止结果集过大ANALYZE TABLE t UPDATE HISTOGRAM ON col),但仅影响优化器执行计划,不提供直接查询接口SELECT city, COUNT(*) AS freq FROM users GROUP BY city ORDER BY freq DESC LIMIT 10;
不是所有 COUNT() 都快。当查询条件无法命中索引、或需要实时精确值时,MySQL 不得不遍历聚簇索引,I/O 开销陡增。
COUNT(*) WHERE create_time > '2025-01-01':若 create_time 无索引,就是全表扫描COUNT(DISTINCT large_text_col):文本字段去重内存压力大,建议先 SUBSTRING 截取前缀再统计table_counts)+ 触发器或应用层维护,而非每次 COUNT(*)
真正难的不是写出语句,而是判断「这个 COUNT 是否必须实时
