SQL 优化(二) 快速计算 Distinct Count原创文章,转载请务必将下面这段话置于文章开头处。 本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/03/15/count_distinct UV vs. PV在互联网中,经常需要计算 UV 和 PV。所谓 PV 即 Page View,网页被打开多少次(YouTube 等视频网站非常重视视频的点击率,即被播放多少次,也即 PV)。而 UV 即 Unique Visitor(微信朋友圈或者微信公众号中的文章则统计有多少人看过该文章,也即 UV。虽然微信上显示是指明该值是 PV,但经笔者测试,实为 UV)。这两个概念非常重要,比如淘宝卖家在做活动时,他往往需要统计宝贝被看了多少次,有多少个不同的人看过该活动介绍。至于如何在互联网上唯一标识一个自然人,也是一个难点,目前还没有一个非常准确的方法,常用的方法是用户名加 cookie,这里不作深究。 count distinct vs. count group by很多情景下,尤其对于文本类型的字段,直接使用 count distinct 的查询效率是非常低的,而先做 group by 更 count 往往能提升查询效率。但实验表明,对于不同的字段,count distinct 与 count group by 的性能并不一样,而且其效率也与目标数据集的数据重复度相关。 本节通过几组实验说明了不同场景下不同 query 的不同效率,同时分析性能差异的原因。 (本文所有实验皆基于 PostgreSQL 9.3.5 平台)
并插入 1000 万条记录,并保证 mac_bigint 为 mac_macaddr 去掉冒号后的 16 进制转换而成的 10 进制 bigint,而 mac_text 为 mac_macaddr 的文本形式,从而保证在这三个字段上查询的结果,并且复杂度相同。 count distinct SQL 如下
count group by SQL 如下
对于不同记录数较大的情景(1000 万条记录中,有 300 多万条不同记录),查询时间(单位毫秒)如下表所示。
对于不同记录数较小的情景(1000 万条记录中,只有 1 万条不同记录),查询时间(单位毫秒)如下表所示。
从上面两组实验可看出,在不同记录数较小时,count group by 性能普遍高于 count distinct,尤其对于 text 类型表现的更明显。而对于不同记录数较大的场景,count group by 性能反而低于直接 count distinct。为什么会造成这种差异呢,我们以 macaddr 类型为例来对比不同结果集下 count group by 的 query plan。 当结果集较小时,planner 会使用 HashAggregation。
|