首页 存档 技术 查看内容

SQL优化(二)快速计算DistinctCount SQL 优化(二) 快速计算 Distinct Count UV vs. ...

2018-3-30 13:00 |来自: 互联网 618 0

摘要: SQL 优化(二) 快速计算 Distinct Count 原创文章,转载请务必将下面这段话置于文章开头处。 本文转发自Jason’s Blog,原文链接 http://www.jasongj.com/2015/03/15/count_distinct UV vs. PV 在互联网中 ...

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 平台)


分别使用 count distinct 和 count group by 对 bigint, macaddr, text 三种类型的字段做查询。


首先创建如下结构的表

COLUMN TYPE MODIFIERS
mac_bigint bigint
mac_macaddr macaddr
mac_text text


并插入 1000 万条记录,并保证 mac_bigint 为 mac_macaddr 去掉冒号后的 16 进制转换而成的 10 进制 bigint,而 mac_text 为 mac_macaddr 的文本形式,从而保证在这三个字段上查询的结果,并且复杂度相同。


count distinct SQL 如下

1
2
3
4
select 
count(distinct mac_macaddr)
from
testmac

count group by SQL 如下

1
2
3
4
5
6
7
8
9
select
count(*)
from
(select
mac_macaddr
from
testmac
group by
1) foo


对于不同记录数较大的情景(1000 万条记录中,有 300 多万条不同记录),查询时间(单位毫秒)如下表所示。

QUERY / 字段类型 MACADDR BIGINT TEXT
count distinct 24668.023 13890.051 149048.911
count group by 32152.808 25929.555 159212.700


对于不同记录数较小的情景(1000 万条记录中,只有 1 万条不同记录),查询时间(单位毫秒)如下表所示。

QUERY / 字段类型 MACADDR BIGINT TEXT
count distinct 20006.681 9984.763 225208.133
count group by 2529.420 2554.720 3701.869


从上面两组实验可看出,在不同记录数较小时,count group by 性能普遍高于 count distinct,尤其对于 text 类型表现的更明显。而对于不同记录数较大的场景,count group by 性能反而低于直接 count distinct。为什么会造成这种差异呢,我们以 macaddr 类型为例来对比不同结果集下 count group by 的 query plan。

当结果集较小时,planner 会使用 HashAggregation。

1
2
3
4
5
6
explain analyze select count(*) from (select mac_macaddr from testmac_small group by 1) foo;
QUERY PLAN
Aggregate (cost=668465.04..668465.05 rows=1 width=0) (actual time=9166.486..9166.486 rows=1 loops=1)
-
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类