distinct通常比group by快,因其仅去重而不触发聚合逻辑,优化器可用哈希或排序一次性完成;group by即使无聚合函数也需预留分组上下文,常引入aggregate节点及额外开销。

为什么 DISTINCT 比 GROUP BY 快(多数情况下)
因为 DISTINCT 是语义更轻的操作:它只做去重,不触发分组聚合逻辑。数据库优化器通常能用哈希或排序一次性完成去重;而 GROUP BY 默认预留了聚合上下文(哪怕没写 AVG()、COUNT()),执行计划里常多出 Aggregate 节点,带来额外开销。
常见错误现象:SELECT DISTINCT col1 FROM t 和 SELECT col1 FROM t GROUP BY col1 返回结果一样,但后者执行时间明显长、CPU 占用高——尤其在大表 + 无索引列上。
- 使用场景:仅需唯一值列表(如下拉筛选项、枚举去重),别用
GROUP BY - 参数差异:两者语法不可互换——
GROUP BY后字段必须出现在SELECT列表中(除非用聚合函数),DISTINCT没这限制 - 性能影响:PostgreSQL 14+ 对单字段
DISTINCT会自动优化为GROUP BY等价形式,但 MySQL 8.0 仍严格区分,建议实测EXPLAIN ANALYZE
GROUP BY 不加聚合函数时,其实悄悄干了什么
当你写 SELECT col1 FROM t GROUP BY col1,表面看和 DISTINCT 一样,但数据库必须确保“每组只返回一行”。问题在于:哪一行?标准 SQL 要求该列必须是确定性可选的(比如主键或函数依赖列),否则报错;MySQL 默认开启 sql_mode=ONLY_FULL_GROUP_BY 前会随机选一行,PostgreSQL 直接拒绝执行。
容易踩的坑:SELECT id, name FROM users GROUP BY name 在 MySQL 5.7 下可能返回任意 id,且无法预测——这不是 bug,是未定义行为。
- 使用场景:真需要按某列分组并取关联字段(如最新记录),必须显式用聚合(
MAX(id))或窗口函数(ROW_NUMBER() OVER (PARTITION BY name ORDER BY updated_at DESC)) - 兼容性影响:SQLite 允许非确定性
GROUP BY,但结果不可移植;生产环境应禁用ONLY_FULL_GROUP_BY关闭状态 - 示例:
SELECT name, MAX(created_at) FROM users GROUP BY name安全;SELECT id, name FROM users GROUP BY name危险
索引对 DISTINCT 和 GROUP BY 的影响完全不同
DISTINCT 能直接受益于覆盖索引:如果查询字段都在索引中(如 CREATE INDEX idx_name ON users(name)),数据库扫索引就能完成去重,避免回表。而 GROUP BY 即使走索引,也常因需要分组中间态而无法跳过排序/哈希阶段。
常见错误现象:给 name 加了索引,DISTINCT name 变快了,但 GROUP BY name 执行计划里仍有 Using temporary; Using filesort。
- 性能影响:复合索引
(a, b)能加速SELECT DISTINCT a, b,但对GROUP BY a, b效果取决于是否含聚合字段 - 实操建议:用
EXPLAIN看Extra字段——出现Using index for group-by(MySQL)才算真正用上索引优化 - 注意点:PostgreSQL 中
GROUP BY可利用索引避免排序,但前提是ORDER BY与GROUP BY字段一致且方向相同
什么时候 GROUP BY 反而比 DISTINCT 更合适
当你需要分组后进一步计算,或者字段组合本身天然具备函数依赖关系时。GROUP BY 是语义正确的起点,硬套 DISTINCT 会掩盖意图、增加维护风险。
容易被忽略的地方:有些 ORM 或 BI 工具自动生成 GROUP BY(比如拖拽字段后点“去重”),你以为它等价于 DISTINCT,其实底层可能已嵌入隐式聚合逻辑,导致后续加字段时突然报错或结果异常。
- 使用场景:统计类查询(
COUNT(*),AVG(price))、按时间窗口聚合(GROUP BY DATE(created_at))、关联子查询中作为派生表 - 参数差异:
GROUP BY支持ROLLUP、CUBE等扩展,DISTINCT完全不支持 - 实操提醒:不要为了“看起来简洁”把
GROUP BY x改成DISTINCT x——即使当前没聚合函数,业务逻辑可能很快需要加











