MySQL 5.7与8.0的GROUP BY行为差异核心在于:ONLY_FULL_GROUP_BY校验更严格,且隐式排序被彻底移除;8.0严格执行SQL标准,要求非聚合列必须出现在GROUP BY中或被聚合函数包裹,并取消结果隐含顺序,必须显式ORDER BY保证排序。

MySQL 5.7 和 8.0 的 GROUP BY 行为不一致,核心就两点:ONLY_FULL_GROUP_BY 校验更严 + 隐性排序被彻底移除。这不是 bug,是 MySQL 主动向 SQL 标准靠拢的结果。
ONLY_FULL_GROUP_BY 默认启用且校验更严格
5.7 虽默认开启该模式,但对“函数依赖”的判断较宽松;8.0 则严格执行标准,要求每个非聚合列要么出现在 GROUP BY 中,要么被 MAX()、ANY_VALUE() 等包裹。
- 典型报错:
Expression #2 of SELECT list is not in GROUP BY clause—— 意思是 SELECT 列表第 2 个字段(比如product)既没进分组,也没聚合 - 即使你把主键加进
GROUP BY,如果表没明确定义主键或唯一约束,8.0 仍可能报not functionally dependent -
ANY_VALUE()可用,但它只是显式声明“我接受不确定值”,不能替代语义正确的改写(比如查“每组最新一条记录”就不能只套ANY_VALUE(created_at))
GROUP BY 不再隐含排序
5.7 下多数 GROUP BY 查询结果看起来有序,是因为优化器常走索引扫描或 filesort;8.0 明确取消该副作用,结果顺序完全不保证。
- 旧 SQL:
SELECT category, COUNT(*) FROM products GROUP BY category;在 5.7 中大概率按category升序返回,在 8.0 中顺序随机 - 分页逻辑若依赖这个“假有序”,升级后可能翻页错乱、数据重复或漏掉
- 必须显式加
ORDER BY才能确保顺序,哪怕只是ORDER BY category
执行计划差异影响性能表现
流聚合(Streaming Aggregate)和哈希聚合(Hash Aggregate)的选用策略变了,同一 SQL 在两版本中可能走完全不同路径。
- 5.7 更倾向用索引+流聚合,哪怕索引不理想也硬上,容易导致慢查询
- 8.0 优化器成本估算更激进:若分组键基数大、key size 高,可能跳过索引,改用哈希聚合甚至磁盘临时表
- 原来靠索引“蒙对”的查询,在 8.0 下可能突然变慢——不是配置问题,是优化器更诚实了
真正麻烦的不是语法报错,而是那些没报错却悄悄变了行为的地方:排序没了、选值随机了、执行计划偏移了。这些点不写进测试用例,上线后才暴露,排查成本远高于提前修正 SQL。


















