Snowflake中SELECT DISTINCT与GROUP BY性能对比及正确用法咨询
两种写法的核心差异&合理性判断
首先要明确这两种写法的返回结果逻辑完全不同,优先看是否匹配你的业务需求:
- 第一种用
distinct ID, NAME的写法:如果同一个ID存在多个不同的NAME(就像你示例里ID=112同时有John Doe和Jane Bow两条记录),去重后同一个ID会返回多条记录,和左表join后会导致左表对应ID的行被重复关联,最终结果行数超出预期。只有当你业务上确实需要匹配同一个ID下所有NAME组合时,这个写法才是合理的。 - 第二种用
group by ID+any_value的写法:同一个ID只会返回一条记录,不会出现关联后行数膨胀的问题,更符合大多数「用ID关联维度属性」的业务场景。但*any_value返回的是该ID下随机一条NAME值,结果是不可控的*,如果你的业务要求同一个ID的NAME取值固定,这个写法存在逻辑隐患。
从性能层面看,在Snowflake引擎中第二种写法执行效率更高:distinct需要对两个字段组合去重,而group by ID仅针对单个字段分组,计算量更小;如果右表有ID作为集群键(Clustering Key),分组的效率还会进一步提升。
更优的实现方案
根据不同的业务场景可以选择更稳妥、性能更好的写法:
- 需要固定取同一个ID下的某条NAME(比如最新更新的)
用窗口函数qualify语法实现,比分组写法更简洁,结果也完全可控:
select left.*, right.name from LEFT_TABLE left inner join ( select ID, NAME from RIGHT_TABLE -- 按PK倒序取每个ID最新的一条,排序规则可根据业务调整 qualify row_number() over (partition by ID order by PK desc) = 1 ) right on left.id = right.id;
- 确认同一个ID下所有NAME都相同,仅需要去重
可以直接用max/min聚合NAME,结果固定,性能也优于any_value和distinct:
select left.*, right.name from LEFT_TABLE left inner join ( select ID, max(NAME) as NAME from RIGHT_TABLE group by ID ) right on left.id = right.id;
- 长期性能优化建议
如果RIGHT_TABLE经常需要按ID关联查询,可以给表设置集群键clustering key (ID),减少查询时的扫描数据量,大幅提升聚合和关联的效率。
内容的提问来源于stack exchange,提问作者Jared DuPont
相关产品推荐
相关产品推荐

