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>