合理设计索引可加速group by:索引应按where列、group by列、order by列顺序覆盖,遵循最左前缀原则;避免在分组或条件中对字段使用函数或隐式类型转换。

GROUP BY 本身不直接使用索引,但合理设计索引能显著加速分组聚合过程——关键在于让数据库先通过索引快速定位/排序数据,再执行分组,避免全表扫描和临时文件排序。
哪些列该加索引?
索引需覆盖 GROUP BY 列 + WHERE 条件列 + ORDER BY 列(如有),且顺序很重要:
- 最左前缀原则:WHERE 条件列应放在索引最左侧(用于快速过滤)
- GROUP BY 列紧随其后(用于有序分组,避免 filesort)
- 若 SELECT 中有非聚合字段(如 MAX(col)、SUM(val)),且这些字段也在索引中,可能触发“索引覆盖”,避免回表
例如:SELECT dept, COUNT(*) FROM emp WHERE status = 'active' GROUP BY dept;
推荐索引:INDEX(status, dept)。这样过滤后数据天然按 dept 有序,分组无需额外排序。
避免隐式类型转换与函数操作
一旦在 GROUP BY 或 WHERE 中对字段做函数处理或类型转换,索引大概率失效:
- ❌
GROUP BY YEAR(create_time)→ 时间索引无法使用 - ❌
GROUP BY UPPER(name)→ 字符索引失效 - ❌
WHERE user_id = '123'(user_id 是 INT)→ 字符串比较引发隐式转换 - ✅ 改为范围预处理:
WHERE create_time >= '2024-01-01' AND create_time
小结果集优先:用 LIMIT 或预过滤缩小分组范围
分组性能与输入行数强相关。即使有索引,千万级表全量分组仍慢。可考虑:
- 加有效 WHERE 条件,提前过滤掉 90% 无用数据
- 业务允许时,用
LIMIT配合子查询或窗口函数取 Top-N 分组(如“销量前 10 的品类”) - 对高频分组维度建汇总表或物化视图(如按天/按区域预聚合),查时直接读聚合结果
检查执行计划,确认是否用上索引
务必用 EXPLAIN FORMAT=TREE(MySQL 8.0+)或 EXPLAIN ANALYZE(PostgreSQL)验证:
- 看 type 是否为 ref / range / const(非 ALL 或 index)
- 看 Extra 是否出现 Using temporary; Using filesort —— 出现即说明分组未走索引排序,性能瓶颈在此
- 观察 rows 预估扫描行数,是否远超实际返回的分组数
如果发现没走索引,优先检查字段类型一致性、NULL 值处理(WHERE col IS NOT NULL 有时能激活索引)、以及统计信息是否过期(可运行 ANALYZE TABLE 更新)。










