count(*)慢的主因是where未走索引导致全表扫描;应通过explain检查type是否为all/index,优先使用ref/range;复合索引需按查询顺序创建,避免在索引字段上使用函数。

WHERE 条件没走索引,COUNT(*) 会慢得离谱
聚合查询卡在 COUNT(*) 或 SUM() 上,大概率不是函数本身的问题,而是数据库先全表扫描再聚合。关键看 WHERE 子句能否命中索引。
- 检查执行计划:用
EXPLAIN看type是否为ALL(全表)或index(全索引扫描),理想是ref/range - 复合索引要注意字段顺序:比如查询
WHERE status = 'active' AND created_at > '2024-01-01',索引应建为(status, created_at),反过来效果差很多 - 避免在索引字段上用函数:写成
WHERE DATE(created_at) = '2024-01-01'会让索引失效,改成WHERE created_at >= '2024-01-01' AND created_at
GROUP BY 字段没索引,临时表和 filesort 就来了
GROUP BY 不只是分组逻辑,它直接触发排序、临时表甚至磁盘临时表(Using temporary; Using filesort)。索引能绕过大部分开销。
95Shop可以免费下载使用,是一款仿醉品商城网店系统,内置SEO优化,具有模块丰富、管理简洁直观,操作易用等特点,系统功能完整,运行速度较快,采用ASP.NET(C#)技术开发,配合SQL Serve2000数据库存储数据,运行环境为微软ASP.NET 2.0。95Shop官方网站定期开发新功能和维护升级。可以放心使用! 安装运行方法 1、下载软件压缩包; 2、将下载的软件压缩包解压缩,得到we
- 单字段
GROUP BY user_id,确保user_id有索引(最好是主键或唯一索引) - 多字段
GROUP BY category, region,建联合索引(category, region),顺序要和 GROUP BY 一致 - 如果
SELECT里有非分组字段又没聚合(如SELECT name, COUNT(*) FROM t GROUP BY user_id),MySQL 5.7+ 默认报错,需关掉sql_mode=ONLY_FULL_GROUP_BY或改写
用 COUNT(1) 还是 COUNT(*)?其实没区别,但 COUNT(col) 要小心 NULL
很多人以为 COUNT(1) 比 COUNT(*) 快,实际优化器都转成一样的执行路径——只要不涉及具体列,它们性能完全一致。
-
COUNT(*)和COUNT(1)都统计行数,包括NULL行 -
COUNT(col)只统计col IS NOT NULL的行,如果该列允许NULL且空值多,性能会略差(要逐行判断) - 想快速估算大表总行数?别用
COUNT(*),查information_schema.tables的table_rows(注意:InnoDB 是估算值,不一定准)
聚合结果集太大导致内存溢出或网络阻塞
不是所有慢都因为计算,有时是结果本身太胖:比如 GROUP BY day 返回 365 行还行,GROUP BY user_id 返回百万行就危险了。
- 加
LIMIT前务必确认业务是否允许截断(SELECT COUNT(*) FROM t GROUP BY user_id LIMIT 10很容易误导) - 用
SQL_CALC_FOUND_ROWS已被弃用,替代方案是单独跑一次SELECT COUNT(DISTINCT user_id) FROM t - 聚合后还要 JOIN 其他表?优先考虑把聚合结果物化成临时表或 CTE,避免重复计算(尤其在子查询里嵌套
GROUP BY)
EXPLAIN 多看两眼,比调参有用得多。










