天天看点

HybridDB PostgreSQL "Sort、Group、distinct 聚合、JOIN" 不惧怕数据倾斜的黑科技和原理 - 多阶段聚合

PostgreSQL , Greenplum , JOIN , group by , distinct , 聚合 , 非分布键 , 数据倾斜 , 多阶段聚合

对于分布式系统,数据分布存储,例如随机、哈希分布。

Greenplum数据库支持两种数据分布模式:

1、哈希(指定单个、或多个字段)

2、随机分布(无需指定任何字段)

JOIN,排序,group by,distinct。

1、JOIN涉及非分布键字段

2、排序,如何保证输出顺序全局有序

3、group by非分布键字段

4、distinct设计非分布键字段

一些功能不完整的数据库,可能无法支持以上功能。

Greenplum商业化数十年,功能方面非常完善,那么它有什么秘密法宝呢?

( HybridDB for PostgreSQL基于GPDB开源版本改进而来,已包含这个功能。 )

例子,

tbl_ao_col表是c1的分布键,但是我们group by使用了c398字段,因此看看它是怎么做的呢?请看执行计划的解释。

执行计划解读:

非分布键 GROUP BY,首先会在本地节点group by,然后按GROUP BY字段进行数据重分布,然后再在本地节点GROUP BY,最后返回GROUP BY结果给master节点,返回给用户。

Greenplum会根据group by的字段的distinct值的比例,考虑是直接重分布数据,还是先在本地聚合后再重分布数据(减少重分布的数据量)。

tbl 为 随机分布

非分布键 求distinct,首先会在本地节点hash 聚合,然后按distinct字段进行数据重分布,然后再在本地节点hash 聚合,最后返回结果给master节点,返回给用户。

Greenplum会根据字段的distinct值的比例,考虑是直接重分布数据,还是先在本地聚合后再重分布数据(减少重分布的数据量)。

distinct和group by都是非分布键,Greenplum分布式执行计划优雅的解决了非分布键group by与distinct数据重分布带来的网络传输的问题。

对于两个表JOIN时,采用了非分布键时,Greenplum会自动对数据进行重分布(或者小表使用广播模式)。

PS

join字段有数据倾斜时,需要注意。

本例为1000万个重复ID作为JOIN字段。JOIN重分布后,会落到一个节点。

JOIN两个非分布键

1、merge sort

为了保证全局有序,以及数据排序的效率。

Greenplum使用了merge sort,首先在数据节点本地排序(所有节点并行),然后master节点向segment请求数据,在master节点merge sort合并。

体现了排序的效率。

对于非分布键的分组聚合请求,Greenplum采用了多阶段聚合如下:

第一阶段,在SEGMENT本地聚合。(Greenplum会根据字段的distinct值的比例,考虑是直接重分布数据,还是先在本地聚合后再重分布数据(减少重分布的数据量)。)

第二阶段,根据分组字段,将结果数据重分布。

第三阶段,再次在SEGMENT本地聚合。

第四阶段,返回结果给master,有必要的话master节点调用聚合函数的final func(已经是很少的记录数和运算量)。

1、对于JOIN为分布键的表,Greenplum根据表的大小,选择对这张表根据JOIN列重分布(大表),或广播(小表)。

2、重分布完成后,SEGMENT节点并行的执行本地JOIN。

<a href="https://github.com/digoal/blog/blob/master/201708/20170818_02.md">《Greenplum 行存、列存,堆表、AO表的原理和选择》</a>

<a href="https://github.com/digoal/blog/blob/master/201708/20170821_02.md">《分布式DB(Greenplum)中数据倾斜的原因和解法 - 阿里云HybridDB for PostgreSQL最佳实践》</a>

窗口,强制重分布

<a href="https://github.com/digoal/blog/blob/master/201707/20170726_01.md">《日增量万亿+级 实时分析、数据规整 - 阿里云HybridDB for PostgreSQL最佳实践》</a>

继续阅读