使用子查询可提升 COUNT DISTINCT 速度 50 倍
注:这些技术是通用的,只不过我们选择使用Postgres的语法。使用独特的pgAdminIII生成解释图形。
很有用,但太慢
Count distinct是SQL分析时的祸根,因此它是我第一篇博客的不二选择。
首先:如果你有一个大的且能够容忍不精确的数据集,那像HyperLogLog这样的概率计数器应该是你最好的选择。(我们会在以后的博客中谈到HyperLogLog。)但对于需要快速、精准答案的查询,一些简单的子查询可以节省你很多时间。
让我们以我们一直使用的一个简单查询开始:哪个图表的用户访问量最大?
1
2
3
4
5
6
7
|
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上已经设置了索引,且有比图表和用户数多得多的日志条目。
一千万行数据时,查询需要48秒。要知道原因让我们看一下SQL解析:
它慢是因为数据库遍历了所有日志以及所有的图表,然后join它们,再将它们排序,这些都在真正的group和分组和聚合工作之前。
先聚合,然后Join
group-聚合后的任何工作代价都要低,因为数据量会更小。group-聚合时我们不需使用dashboards.name,我们也可以先在数据库上做聚集,在join之前:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
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 |
现在查询运行了20秒,提升了2.4倍。再次通过解析来看一下原因:
正如设计的,group-聚合在join之前。而且,额外的我们可以利用time_on_site_logs表里的索引。
首先,缩小数据集
我们可以做的更好。通过在整个日志表上group-聚合,我们处理了数据库中很多不必要的数据。Count distinct为每个group生成一个哈希——在本次环境中为每个dashboard_id——来跟踪哪些bucket中的哪些值已经检查过。
我们可以预先计算差异,而不是处理全部数据,这样只需要一个哈希集合。然后我们在此基础上做一个简单的聚集即可。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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 |
我们采取内部的count-distinct-group,然后将数据拆成两部分分成两块。第一块计算distinct (dashboard_id, user_id) 。第二块在它们基础上运行一个简单group-count。跟上面一样,最后再join。
呵呵,大发现:这样只需要0.7秒!这比上面的查询快28倍,比原来的快了68倍。
通常,数据大小和类型很重要。上面的例子受益于基数中没多少换算。distinct (user_id, dashboard_id)相对于数据总量来说数量也很少。不同的对数越多,用来group和计数的唯一数据就越多——代价便会越来越大。
下一遇到长时间运行的count distinct时,尝试一些子查询来减负吧。
原文地址:https://periscope.io/blog/use-subqueries-to-count-distinct-50x-faster.html
使用子查询可提升 COUNT DISTINCT 速度 50 倍的更多相关文章
- Impala的count(distinct QUESTION_ID) 与ndv(QUESTION_ID)
在impala中,一个select执行多个count(distinct col)会报错,举例: select C_DEPT2, count(distinct QUESTION_BUSI_ID) as ...
- postgresql子查询优化(提升子查询)
问题背景 在开发项目过程中,客户要求使用gbase8s数据库(基于informix),简单的分页页面响应很慢.排查发现分页sql是先查询出数据在外面套一层后再取多少条,如果去掉嵌套的一层,直接获取则很 ...
- volatile 函数影响子查询提升
我们知道 volatile 函数会影响SQL的执行性能,比如:volatile 类型函数无法建函数索引.volatile 函数针对每条记录都要执行一次.本篇的例子主要讲述 volatile 类型的函数 ...
- SQL夯实基础(四):子查询及sql优化案例
首先我们先明确一下sql语句的执行顺序,如下有前至后执行: (1)from (2) on (3) join (4) where (5)group by (6) avg,sum... (7 ...
- MySQL高级查询与编程笔记 • 【第3章 子查询】
全部章节 >>>> 本章目录 3.1 子查询定义和单行子查询 3.1.1 子查询定义 3.1.2 单行子查询应用 3.1.4 实践练习 3.2 多行子查询应用 3.2.1 ...
- 【T-SQL基础】03.子查询
以前总是追求新东西,发现基础才是最重要的,今年主要的目标是精通SQL查询和SQL性能优化. 本系列[T-SQL基础]主要是针对T-SQL基础的总结. [T-SQL基础]01.单表查询-几道sql查询题 ...
- sql之独立子查询和相关子查询总结
1.独立子查询:顾名思义:就是子查询和外层查询不存在任何联系,是独立于外层查询的: 下面就看一个例子: 有一张订单表 Sales.Order 和一张 客户表 Sales.Customer 下面的sql ...
- SQL Fundamentals: 子查询 || WHERE,HAVING,FROM,SELECT子句中使用子查询,WITH子句
SQL Fundamentals || Oracle SQL语言 子查询(基础) 1.认识子查询 2.WHERE子句中使用子查询 3.在HAVING子句中使用子查询 4.在FROM子句中使用子查询 5 ...
- MySQL子查询的优化
本文基于MySQL5.7.19测试 创建四张表,pt1.pt2表加上主键 mysql> create table t1 (a1 int, b1 int); mysql> create ta ...
随机推荐
- pimpl idiom
pimpl idiom flyfish 2014-9-30 pimpl是Pointer to implementation的缩写 为什么要使用pimpl 1最小化编译依赖 2接口与实现分离 3可移植 ...
- APP三种开发模式
目前主流应用程序大体分为三种:Web App(网页应用).Hybrid Ap(混合应用)p. Native App(原生应用). nativeapp是一个原生程序,一般运行在机器操作系统上,有很强的交 ...
- 17monipdb根据IP获得区域
https://www.ipip.net/download.html https://github.com/17mon/csharp IpAndPositionHelper public class ...
- Mac - 使用php环境
按下shift + Command + G ,输入以下php(www)路径 /Library/WebServer/Documents 打开终端,输入以下命令打开环境 sudo apachectl s ...
- 【转】python2与python3的主要区别
摘自:http://www.cnblogs.com/codingmylife/archive/2010/06/06/1752807.html 1.性能 Py3.0运行 pystone benchmar ...
- 关于HTTP协议(未完)
转 : https://www.cnblogs.com/ranyonsue/p/5984001.html
- C++中虚基类在派生类中的内存布局
今天重温C++的知识,当看到虚基类这点的时候,那时候也没有太过追究,就是知道虚基类是消除了类继承之间的二义性问题而已,可是很是好奇,它是怎么消除的,内存布局是怎么分配的呢?于是就深入研究了一下,具体的 ...
- Sampling and Estimation
Sampling and Estimation Sampling Error Sampling error is the difference between a sample statistic(t ...
- 【Android】9.3 自定义列表视图的外观
分类:C#.Android.VS2015: 创建日期:2016-02-18 一.简介 自定义的列表视图通常用Resources/Layout文件夹下的axml文件中的资源来声明,适配器则通过Id去加载 ...
- 【Android】5.6 弹出菜单(PopUp Menus)
分类:C#.Android.VS2015: 创建日期:2016-02-07 一.简介 功能描述:用户单击按钮弹出菜单.当用户选择一个菜单项,会触发MenuItemClick事件并让弹出的菜单消失:如果 ...