MySQL 5.7开启ONLY_FULL_GROUP_BY时分组取首行查询优化
MySQL 5.7 分组取最小ID对应大字段查询优化方案
原查询慢的核心原因
- 缺失针对性索引:原表仅主键索引,子查询按
event_id分组取MIN(id)时,需全表扫描过滤目标event_id后再分组计算,效率极低。 IN子查询性能瓶颈:MySQL对多值IN子查询的优化逻辑不如JOIN高效,易导致主查询多次匹配扫描。- 大字段IO开销:
image是mediumtext大字段,无索引支持时回表读取会占用大量IO资源。
优化方案
1. 创建复合索引
先给eventImages表创建(event_id, id)复合索引,该索引可直接覆盖子查询的WHERE过滤、GROUP BY分组及MIN(id)计算,全程无需回表:
CREATE INDEX idx_event_id_id ON eventImages(event_id, id);
2. 替换IN子查询为JOIN
改用JOIN关联子查询结果,MySQL对JOIN的执行计划优化更成熟,能大幅提升查询效率:
SELECT ei.id, ei.event_id, ei.image FROM eventImages ei JOIN ( SELECT event_id, MIN(id) AS min_id FROM eventImages WHERE event_id IN (4610, 4609, 4608, 4607, 4606, 4605, 4604, 4603, 4602, 4601) GROUP BY event_id ) ei_min ON ei.id = ei_min.min_id ORDER BY ei.event_id DESC;
说明:子查询通过新索引快速得到每个event_id对应的最小id,主查询直接通过主键id关联读取目标记录,彻底避免全表扫描和多次匹配的开销。
3. 长期优化建议
- 若此类查询频率高,可维护一张缓存表(如
event_min_image_id),定期同步各event_id对应的最小id,查询时直接关联缓存表,省去分组计算步骤。 - 尽量减少不必要的
image字段查询,大字段读取会占用大量IO,仅在业务必需时才包含该字段。
内容的提问来源于stack exchange,提问作者IvanNaStackOF
相关产品推荐
相关产品推荐

