DISTINCT是专为去重设计的语义操作,GROUP BY本质用于分组聚合;仅需去重时,DISTINCT逻辑更轻、优化路径更直接,无索引时GROUP BY可能多触发Using filesort。
MySQL 中
和
去重,本质不是“谁更快”,而是“谁更贴合语义”
直接说结论:
是专为去重设计的语义操作,
是为分组聚合设计的;当仅需去重、不带聚合时,
逻辑更轻、优化路径更直接。强行用
实现纯去重,MySQL 有可能多走一步排序(
),尤其在无索引列上。
的执行路径:哈希去重 or 索引扫描,不默认排序
MySQL 对
的常见实现方式有两种:
小结果集:构建内存哈希表,逐行插入并去重,最后输出;
有覆盖索引时:直接走
(注意名字里有 group-by,但实际是优化器复用路径,并不真做分组);
不强制对结果排序,除非你显式加了
;
例如:
如果
有索引,Explain 显示
+
,基本就是索引扫描一遍完事。
的执行路径:分组 → 排序(可能)→ 取首行
即使你只写
,MySQL 内部仍按分组逻辑处理:
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
若
无索引:先建临时表,再对分组键排序(触发
),然后每组取第一行;
若
有索引且是前导列:可走松散/紧凑索引扫描,跳过排序,效率接近
;
一旦语句里出现非分组列(如
),MySQL 5.7+ 默认报错(
),必须用聚合函数或明确指定取值逻辑;
所以,
在纯去重场景下,多一层语义负担和潜在排序开销。
什么时候
反而更优?别被“去重”二字带偏
真正影响选择的不是“哪个快”,而是你要不要后续扩展能力:
需要统计每个城市的用户数?必须用
,
不支持聚合;
要去重后过滤分组(比如只保留出现次数 ≥ 5 的城市)?只能用
,
没这功能;
要联合多列去重,且其中一列有高基数索引(如
),
有时能更好利用覆盖索引,避免回表;
简单说:没聚合就用
;要聚合、要
、要复用已有复合索引结构,就选
—— 效率差异往往藏在索引是否匹配、是否触发
这些细节里,而不是关键字本身。
DISTINCTGROUP BYDISTINCTGROUP BYDISTINCTGROUP BYUsing filesortDISTINCTDISTINCTUsing index for group-byORDER BYSELECT DISTINCT city FROM users;citytype: indexExtra: Using indexGROUP BYSELECT city FROM users GROUP BY city;cityUsing filesortcityDISTINCTSELECT city, name FROM users GROUP BY citysql_mode=only_full_group_byGROUP BYGROUP BYGROUP BY city COUNT(*)DISTINCTHAVINGDISTINCT(status, created_at)GROUP BYDISTINCTHAVINGGROUP BYfilesort