前言
兄弟我错了!我不该怼你!
之前因为同事用distinct直接导致SQL链接超时(执行需要18s),改成group by 之后就好了(2s左右),然后我怼了他。详情见文章【完了演示的时候报错了!distinct 别乱用啊】。
当时写了这篇文章,我以为group by 在复杂的sql中通常比distinct 好,最近看到好多文章都说distinct 性能优于group by。但是在我在实际开发中,却发现不同情况下两者的效率也是不同的,甚至相差10倍。
本文实验结论:
不能脱离实际的数据情况,来谈group by 和 distinct 的效率
因为group by 的查询时间可能比 distinct 查询时间 快10倍【案例二】(pgsql 对group by 排序字段做了优化),
distinct也可能比group by 性能快10【案例一】.
案例测试
实验具有一定局限性,仅供参考
案例一
环境mysql 9.1.0版本
案例SQL:
goods_test_one数据量在90w ,goods_test_two 数据量在20w,大量数据为重复数据。
SELECT DISTINCT o.goods_code,o.goods_id,o.product_id,o.out_lookc,o.model,o.drug_code,o.sys_code,o.goods_code_two,
o.goods_id_two,o.product_id_two,o.out_lookc_two,o.model_two
,o.drug_code_two,o.sys_code_two,t.goods_code
FROM goods_test_one o LEFT JOIN goods_test_two t on o.goods_code = t.goods_code
WHERE o.drug_code is not null
LIMIT 1200
测试结果
执行计划一样,但是实际执行时间相差 distinct 执行效率确实 group by 的 100倍
- distinct 执行时间 1.17s
- group by 执行时间 159s
- 执行计划都一样
案例二
案例SQL
环境人大金仓数据库,数据量在1万条。sql 如下,具体字段不方便展示
(用人大金仓的原因因为我现在工作中就用的这个)
测试结果
这次是group by 效率领先6倍,可能是数据量小吧,主表数据就1万左右,这个差距也很大了。从执行计划来看是因为group by 在 排序和分组的时候做了优化,只根据3个字段去重了
- distinct 时长 18s
2. group by 2.8s
案例三
把【案例二】的sql微调一下,减少一个 去重字段,把 ua.id 去了 。这时候group by 和 distinct 的执行结果就发生了变化
案例SQl
测试结果
-
distinct 耗时18s
执行计划如图: -
group by 耗时18s
执行计划如图:
总结
人大金仓的内核是PGSQL,我们假定 和 mysql 在实现 group by 和 distinct 原理一样的情况下,至少我们能得出的结论是,不能绝对的说 distinct 和 group by 谁的性能好,一定要基于数据和具体的查询语句。
从【案例二】 和 【案例三】来看,在pgsql 环境,group by 可能会对排序进行优化,减少排序 和 分组的字段
影响 distinct 和 group by 的因素
下面是在网上找到的一些博客,可供大家参考。网络上大多的文章都是和第一条的观点相似。第二条文章的观点确实意想不到。
- 语义相同的条件效,无索引情况,distinct 效率更高,否则几乎等效。
(文章链接:developer.aliyun.com/article/120… - 某些复杂的场景,group by 效率可能更高。
DISTINCT 收集所有行,包括需要计算的表达式,计算之后再丢掉重复项。GROUP BY 在执行其他工作之前就把重复项丢弃。
(文章链接:sqlperformance.com/2017/01/t-s…原话: DISTINCT collects all of the rows, including any expressions that need to be evaluated, and then tosses out duplicates. GROUP BY can (again, in some cases) filter out the duplicate rows before performing any of that work