在 MySQL 中,DISTINCT 和 GROUP BY 都能实现去重,但平时应该怎么用才能做到效能最高呢?
其实,它们在实现机制、功能定位和性能特征上有着本质区别。
结论如果只是去重就用 DISTINCT。DISTINCT是SQL专门为去重设计的关键字,它的核心使命很简单:去除重复行,返回唯一值。
如果要分组聚合,只能使用 GROUP BY。GROUP BY的设计初衷就是是对数据进行分组聚合,DISTINCT不具备聚合的能力。
原理对比DISTINCT执行原理
1. 扫描表数据2. 在内存/临时表中维护已出现的值集合3. 对于每行,检查是否已存在于集合中4. 如果不存在则输出并加入集合5. 如果存在则跳过GROUP BY执行原理
1. 扫描表数据2. 根据 GROUP BY 列计算哈希值或排序3. 相同分组键的行聚集在一起4. 每组选出一条代表行(不去聚合函数时)性能对比数据库表
CREATE TABLE `t_user` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键', `name` varchar(100) NOT NULL COMMENT '姓名', `age` int NOT NULL COMMENT '年龄', PRIMARY KEY (`id`), KEY `idx_age` (`age`)) ENGINE=InnoDB CHARSET=utf8mb4 COMMENT='用户表'有索引时
两者都使用索引,执行计划相同;性能几乎一样。
无索引时
MySQL 8.0 之前,GROUP BY 会进行 隐式排序,会触发filesort,导致性能下降;而 DISTINCT 不需要这种排序,因此在无索引时 DISTINCT 性能更优。
怎么提高 GROUP BY 效能? 最直接的办法就是建索引,如果不能建还可以显示写上 ORDER BY NULL 来取消 group by 结果的排序,如下:
MySQL 8.0开始,GROUP BY的隐式排序已被移除,两者在无索引情况下的性能差异大大缩小。
场景
推荐用法
核心原因
纯去重(无聚合)
DISTINCT
逻辑简洁,无索引时效率略高
去重+聚合(COUNT/SUM 等)
GROUP BY
唯一能实现聚合的方式
去重+过滤分组结果
GROUP BY + HAVING
DISTINCT 无分组过滤能力
有索引的任意去重场景
两者皆可
索引消除了效率差异
最后记住核心原则:DISTINCT 是 "去重" 的 ,GROUP BY 是 "分组聚合" 的。
在实际开发中,不用纠结 “谁绝对更好”,而是先明确业务需求(是否聚合、是否过滤),再结合索引情况选择;写完 SQL 后,养成看执行计划(EXPLAIN)的习惯,通过 Extra 字段判断是否需要优化,优化的首要选择还是 索引,这才是提升 MySQL 性能的核心思路。
转载请注明来自海坡下载,本文标题:《distinct优化(优化 MySQL 去重DISTINCT vs GROUP BY )》
京公网安备11000000000001号
京ICP备11000001号
还没有评论,来说两句吧...