tidb和tbase的聚合函数算法
tidb的聚合函数算法
连接:(二十二)Hash Aggregation
tidb实现了两种聚合函数的算法:Hash Aggregation 和 Stream Aggregation
对于数据无序的,使用Hash Aggregation。
对于数据按照groupby字段有序的,使用Stream Aggregation。
以avg聚合函数作为例子,在执行时需要维护两个中间值sum和count。
Hash Aggregation
在 Hash Aggregate 的计算过程中,我们需要维护一个 Hash 表,Hash 表的键为聚合计算的 Group-By
列,值为聚合函数的中间结果 sum
和 count
。在本例中,键为 列 a
的值,值为 sum(b)
和 count(b)
。
计算过程中,只需要根据每行输入数据计算出键,在 Hash 表中找到对应值进行更新即可。对本例的执行过程模拟如下。
输入数据 a b
|
Hash 表 [key] (sum, count)
|
---|---|
1 9 |
[1] (9, 1)
|
1 -8 |
[1] (1, 2)
|
2 -7 |
[1] (1, 2) [2] (-7, 1)
|
2 6 |
[1] (1, 2) [2] (-1, 2)
|
1 5 |
[1] (6, 3) [2] (-1, 2)
|
2 4 |
[1] (6, 3) [2] (3, 3)
|
输入数据输入完后,扫描 Hash 表并计算,便可以得到最终结果:
Hash 表 |
avg(b)
|
---|---|
[1] (6, 3)
|
2 |
[2] (3, 3)
|
1 |
Stream Aggregation
Stream Aggregate 的计算需要保证输入数据按照 Group-By
列有序。在计算过程中,每当读到一个新的 Group 的值或所有数据输入完成时,便对前一个 Group 的聚合最终结果进行计算。
对于本例,我们首先对输入数据按照 a
列进行排序。排序后,本例执行过程模拟如下。
输入数据 | 是否为新 Group 或所有数据输入完成 |
(sum, count) | avg(b)
|
|
---|---|---|---|
1 9 | 是 | (9, 1) | 前一个 Group 为空,不进行计算 |
1 -8 | 否 | (1, 2) | |
1 5 | 否 | (6, 3) | |
2 -7 | 是 | (-7, 1) | 2 |
2 6 | 否 | (-1, 2) | |
2 4 | 否 | (3, 3) | |
是 | 1 |
因为 Stream Aggregate 的输入数据需要保证同一个 Group 的数据连续输入,所以 Stream Aggregate 处理完一个 Group 的数据后可以立刻向上返回结果,不用像 Hash Aggregate 一样需要处理完所有数据后才能正确的对外返回结果。当上层算子只需要计算部分结果时,比如 Limit,当获取到需要的行数后,可以提前中断 Stream Aggregate 后续的无用计算。
当 Group-By
列上存在索引时,由索引读入数据可以保证输入数据按照 Group-By
列有序,此时同一个 Group 的数据连续输入 Stream Aggregate 算子,可以避免额外的排序操作。
聚合的类型
由于分布式计算的需要,TiDB 对于聚合函数的计算阶段进行划分,相应定义了 5 种计算模式:CompleteMode,FinalMode,Partial1Mode,Partial2Mode,DedupMode。不同的计算模式下,所处理的输入值和输出值会有所差异,如下表所示:
AggFunctionMode | 输入值 | 输出值 |
---|---|---|
CompleteMode | 原始数据 | 最终结果 |
FinalMode | 中间结果 | 最终结果 |
Partial1Mode | 原始数据 | 中间结果 |
Partial2Mode | 中间结果 | 进一步聚合的中间结果 |
DedupMode | 原始数据 | 去重后的原始数据 |
并行聚合的操作
TiDB 的并行 Hash Aggregation 算子执行过程中的主要线程有:Main Thead,Data Fetcher,Partial Worker,和 Final Worker:
- Main Thread 一个:
- 启动 Input Reader,Partial Workers 及 Final Workers
- 等待 Final Worker 的执行结果并返回
- Data Fetcher 一个:
- 按 batch 读取子节点数据并分发给 Partial Worker
- Partial Worker 多个:
- 读取 Data Fetcher 发送来的数据,并做预聚合
- 将预聚合结果根据 Group 值 shuffle 给对应的 Final Worker
- Final Worker 多个:
- 读取 PartialWorker 发送来的数据,计算最终结果,发送给 Main Thread
Hash Aggregation 的执行阶段可分为如下图所示的 5 步:
启动 Data Fetcher,Partial Workers 及 Final Workers。
这部分工作由 prepare4Parallel 函数完成。该函数会启动一个 Data Fetcher,多个 Partial Worker 以及 多个 Final Worker。Partial Worker 和 Final Worker 的数量可以分别通过
tidb_hashgg_partial_concurrency
和tidb_hashagg_final_concurrency
系统变量进行控制,这两个系统变量的默认值都为 4。DataFetcher 读取子节点的数据并分发给 Partial Workers。
这部分工作由 fetchChildData 函数完成。
Partial Workers 预聚合计算,及根据 Group Key shuffle 给对应的 Final Workers。
这部分工作由 HashAggPartialWorker.run 函数完成。该函数调用 updatePartialResult 函数对 DataFetcher 发来数据执行 预聚合计算,并将预聚合结果存储到 partialResultMap 中。其中
partialResultMap
的 key 为根据Group-By
的值 encode 的结果,value 为 PartialResult 类型的数组,数组中的每个元素表示该下标处的聚合函数在对应 Group 中的预聚合结果。shuffleIntermData 函数完成根据 Group 值 shuffle 给对应的 Final Worker。Final Worker 计算最终结果,发送给 Main Thread。
这部分工作由 HashAggFinalWorker.run 函数完成。该函数调用 consumeIntermData 函数 接收 PartialWorkers 发送来的预聚合结果,进而 合并 得到最终结果。getFinalResult 函数完成发送最终结果给 Main Thread。
Main Thread 接收最终结果并返回。
tbase的聚合函数算法
tbase的聚合函数算法介绍:https://cloud.tencent.com/developer/article/1429767
tbase的资料比较少。
我们先看一下什么是社区聚合?社区聚合是对于单节点并行的,用一个Gather算子收集各个DN节点的结果。可优化的方式是把要聚合的表/中间表数据进行分片,分完片后每个worker对应于某一个片进行聚合。第一次聚合完之后(现在只是某一个分片聚合)gather算子会把多个一次聚合的结果,再进行第二次聚合然后得到最终结果。这其中有一个问题是:Gather算子这个地方是没法并行的,这可能是影响性能的一个瓶颈,我们怎么优化呢?
具体优化如下:第一步是一样的,每个分片进行聚合。但聚合完之后不是由gather再次聚合,而是把每个分片都广播到所有的worker上面去,每个worker负责对应某一个分片,这就不需要gather即可直接得到最终结果,也就是说我们第二次聚合也能实现并行。
当然不仅仅是性能的优化,我们知道社区聚合方式一旦有一个聚合算子,整个执行计划的并行度都会受到影响,因为前面所有的结果都是在一个点聚合的。当我们整体并行计算后,能够解决聚合算子成为并行执行当中的独木桥的问题。效率会提升,整个并行度大幅增加。
tbase和tidb的聚合算法异同
相同处
- 均使用了并行聚合函数的操作。
- 聚合都有两个阶段,预聚合和最终聚合
- 都用到了hash的方式寻找聚合
- 都采用了预处理结果分发给多个线程的方式来执行最终聚合。
不同处
- tidb除了hash聚合的方式外还实现了流式聚合的方式。
- tidb的预聚合处理和最终聚合处理在不同的线程中处理。tbase的是在一个线程中。
- tbase的聚合阶段有多种类型,最多的有三层聚合操作,tbase看不出,但图中最多为两层。
tidb和tbase的聚合函数算法相关推荐
- oracle中聚合比较函数,Oracle聚合函数/分析函数
oracle函数分两类:单行函数.多行函数.多行函数又分为聚合函数.组合函数,参数为数组,数据大小为记录数,这种数组不是普通高级语言的数组,是一种虚拟数组,当记录数大时,会将数据写入硬盘,内存中放的只 ...
- 阿里云PyODPS 0.7.18发布,针对聚合函数进行优化同时新增对Python 3.7支持
近日,阿里云发布PyODPS 0.7.18,主要是针对聚合函数进行优化同时新增对Python 3.7支持. PyODPS是MaxCompute的Python版本的SDK,SDK的意思非常广泛,辅助开发 ...
- Jdbc访问mysql查询聚合函数_JDBC连接参数设置对Oracle数据库的影响分析
一次数据库性能问题处理引发的JDBC参数设置思考 近期某环境下系统,出现大面积页面访问缓慢情况,每个页面交易响应时间2-5秒,严重超过平日访问阈值. 经排查分析,问题主要出现在数据库,生成AWR得到3 ...
- mysql 聚合函数内比较运算符_关于常用 MYSQL 聚合函数,其他函数 ,类型转换,运算符 总结...
/* 关于MYSQL 聚合函数,其他函数 ,类型转换,运算符 总结,*/ -- 1 运算符优先级 /* 12.1.1. 操作符优先级 以下列表显示了操作符优先级的由低到高的顺序.排列在同一行的操作符 ...
- power bi函数_在Power BI中的行上使用聚合函数
power bi函数 Aggregate functions are one of the main building blocks in Power BI. Being used explicitl ...
- PostgreSQL 10 自定义并行计算聚合函数的原理与实践
标签 PostgreSQL , 聚合函数 , 自定义 , AGGREGATE , 并行 , COMBINEFUNC 背景 PostgreSQL 9.6开始就支持并行计算了,意味着聚合.扫描.排序.JO ...
- MySQL(四)Select总结及补充聚合函数及分组过滤MD5加密
1.聚合函数 案例0:查询学生个数 SELECT COUNT(studentname) FROM student;SELECT COUNT(*) FROM student;SELECT COUNT(1 ...
- MySql基础篇---002 SQL之SELECT使用篇: 基本的SELECT语句,运算符,排序与分页,多表查询,单行函数,聚合函数,子查询
第03章_基本的SELECT语句 讲师:尚硅谷-宋红康(江湖人称:康师傅) 官网:http://www.atguigu.com 1. SQL概述 1.1 SQL背景知识 1946 年,世界上第一台电脑 ...
- ORACLE 11G 聚合函数
聚合函数就是基于多行数据返回一行结果,下面就是Oracle提供的一些列聚合函数: AVG COLLECT CORR CORR_* COUNT COVAR_POP COVAR_SAMP CUME_DIS ...
最新文章
- Visual Studio 压力测试注意点
- C#连接各类数据库 [转]
- php mysql db封装类_封装自己的DB类(PHP)
- 百度网页移动端html,百度移动端开始用网站品牌名代替网址显示
- 天猫整站SSM-后台分类管理-增加(做个人学习笔记整理用)
- 计算机网络学习笔记-1.1.3-速率相关的性能指标
- 机器学习和统计模型的差异
- centos7.3部署django用uwsgi和nginx[亲测可用]
- 如果有5杯水却来了6个领导,你该怎么办?
- DIV+CSS样式表命名的规则方法
- 最值得收藏的 算法分析与设计 全部知识点思维导图整理(北大慕课课程)
- 软考高级 真题 2010年下半年 信息系统项目管理师 综合知识
- python youtube视频_Python3 使用you-get,youtube-dl,ffmpeg 下载全网视频并剪切视频
- 十二星座的来历和希腊神话12主神简介
- LTE相关协议2——下行峰值速率计算
- matlab中options,[转载]Matlab优化函数中options选项的修改
- 服务器 'server_1' 上的 MSDTC 不可用。
- 8086系统中 BHE# 和 A0 引脚
- 【memcached】可视化memcache监控工具memcachephp安装与使用
- pycharm 关闭光标闪烁