如何加速MySQL的Group By查询?300万行数据查询耗时30秒
优化MySQL分组求和慢查询的方案
看来你的按日期分组求和查询在300万行的表上跑了30秒,确实有点拖后腿,咱们来拆解问题并给出针对性的优化方案。
先分析当前执行计划的问题
你提到EXPLAIN结果里type是index,用了一个以UNIQ开头的索引。大概率这个索引不是为当前查询量身打造的——要么它的字段顺序不对,要么没有包含你需要求和的kpi1、kpi2,导致MySQL不得不频繁回表查询主表数据,这是慢查询的核心原因。
最有效的优化:创建覆盖索引
覆盖索引是解决这类分组聚合查询的黄金方案,它能让MySQL直接从索引中获取所有需要的数据,完全不需要回表操作。针对你的查询,你需要创建包含date(分组字段)和kpi1、kpi2(聚合字段)的复合索引:
CREATE INDEX idx_date_kpi ON table_name(date, kpi1, kpi2);
为什么这个索引有效?
- 索引以
date开头,MySQL可以快速按日期分组,避免全表扫描或低效的索引扫描。 kpi1和kpi2被包含在索引中,MySQL不需要再去主表读取这两个字段的值,直接从索引里就能完成求和计算,极大降低了IO开销。
验证优化效果
创建索引后,再次执行EXPLAIN select date, sum(kpi1), sum(kpi2) FROM table_name GROUP BY date;,如果看到Extra列显示Using index,说明覆盖索引已经生效。这时候再跑原查询,耗时应该会从30秒降到几百毫秒甚至更低。
其他辅助优化点
- 过滤不必要的数据:如果你的查询不需要统计所有日期,可以加上
WHERE条件缩小范围,比如WHERE date >= '2023-01-01',进一步减少处理的数据量。 - 检查存储引擎:如果你的表用的是MyISAM,建议换成InnoDB,它在并发场景和缓存机制上表现更好(不过这个优化的优先级低于覆盖索引)。
- 确认索引有效性:先通过
SHOW CREATE TABLE table_name;查看那个UNIQ索引的具体字段,如果它和我们建议的覆盖索引重复,可以考虑删除冗余索引,避免维护成本。
内容的提问来源于stack exchange,提问作者Dany M
相关产品推荐
相关产品推荐

