本文说的这个技术是通用的,但为了解释说明,咱们选用了 PostgreSQL。感谢 pgAdminIII 提供的解释性插图,这些插图有很大帮助。html
计算非重复的数目是SQL分析的一个灾难,显然,咱们要在第一篇博文上讨论。算法
首先一点:咱们若是有一个很大的数据集并且能够容忍它不精确。一个像 HyperLogLog 的几率统计器多是你的首选(咱们在之后的博客中会讲到HyperLogLog ),可是要追求快速精准的结果,子查询的方法会节省你不少时间。数据库
让咱们从一个简单的查询语句开始吧:哪个dashboard用户访问的最频繁。segmentfault
select dashboards.name, count(distinct time_on_site_logs.user_id) from time_on_site_logs join dashboards on time_on_site_logs.dashboard_id = dashboards.id group by name order by count desc
首先,让咱们假设在user_id 和 dashboard_id上都有高效的索引,而且日志行数要比user_id 和 dashboard_id多不少。工具
仅仅一千万行数据,查询语句就花费了48秒的时间。知道为何吗?让咱们看一下明了的图解吧。性能
慢的缘由是数据库要遍历dashboards表和logs表的全部记录,而后JOIN操做,而后排序,以后才进行实际须要的分组和汇集操做。spa
分组和汇集以后,一切数据库操做的代价都变小了,由于数据的数量变小了。在分组和汇集的时候,由于咱们不须要dashboards.name,因此咱们能够在JOIN操做前先进行汇集操做:日志
select dashboards.name, log_counts.ct from dashboards join ( select dashboard_id, count(distinct user_id) as ct from time_on_site_logs group by dashboard_id ) as log_counts on log_counts.dashboard_id = dashboards.id order by log_counts.ct desc
语句运行了24秒,得到了2.4倍的性能提升。在来看一下,图解能够清楚无误的代表缘由。code
像咱们预期地那样,join操做以前先进行了group-and-aggregate操做。快上加快,咱们还能够在time_on_site_logs 表上加上索引。htm
咱们还能够作的更好,咱们对日志表作group-and-aggregate操做时,咱们处理了一些无关的数据,其实没有必要。咱们能够对每一个分组上建立一个哈希集合,这样,在每一个哈希桶中让每一个dashboard_id 挑出那些须要被看处处理的数据。
不用作那么多工做,只用一个哈希集合,咱们就能够先去除那些重复的值。而后咱们在这个结果上作汇集操做。
select dashboards.name, log_counts.ct from dashboards join ( select distinct_logs.dashboard_id, count(1) as ct from ( select distinct dashboard_id, user_id from time_on_site_logs ) as distinct_logs group by distinct_logs.dashboard_id ) as log_counts on log_counts.dashboard_id = dashboards.id order by log_counts.ct desc
咱们让去重和分组汇集一步一步进行,分红两个阶段。首先在(dashboard_id, user_id)对上去重,而后在这基础上作简单快速的分组计算工做,JOIN操做仍是放在最后。
让咱们来揭晓最终效果:总共花费了0.7秒,是上一次的28倍,最初的68倍。
通常来讲,数据大小和数据位置是很重要的,表中的属性字段的可能取值个数相对不多,因此才有那么明显的效果,与数据总量相比较,(user_id, dashboard_id) 对的不一样值不多。越多的不一样的值,各行的数据越分散,因此分组和计算它们花费越长的时间,果真天下没有白吃的午饭。
也许你下次计算非重复结果须要花费一天的时间,试着用子查询的方法减轻它的负载。
咱们作了 Periscope,一个可使SQL数据分析更快的工具。咱们在这里分享一下咱们的工具蕴含的算法和技术。你能够到咱们的主页上注册,从而做为咱们的新客户,咱们能够通知你相关事宜。
原文:Use Subqueries to Count Distinct 50X Faster
转载于:伯乐在线 - sunbiaobiao