Greenplum广播与重分布原理

Greenplum 的执行计划和 PostgreSQL 基本一致,但是在表关联的时候还是会有区别,因为 greenplum 中数据不同于 pg,greenplum 是将数据分布在多个节点上。所以当两表关联时关联列又不是表的分布键时就会出现表的广播和重分布。本文将详细介绍广播和重分布的区别及场景。

在此之前,我们需要先了解下在 greenplum 中表之间分布式关联有哪些类型?
表的分布式关联主要分为两大类:
1、单库关联,即表的关联键和分布键一致,所以只需要在单个库中得到结果后再关联即可,因此也不会涉及到广播和重分布;
2、跨库关联,即表的关联键和分布键不一致,因此数据需要重新分布来达到单库关联的效果,这也是本文主要讲解的地方。

对于跨库关联又分为两种情况:
2.1、一张表的关联键是分布列,另一张表不是;
2.2、两张表的关联键均不是分布列。
详细情况如下图所示 (a、b 两表中 c1 列是分布列):

下面结合实例来讲解广播和重分布的原理及场景。
构建环境:

postgres=# CREATE table a(c1 int,c2 int)distributed by(c1);
CREATE TABLE
postgres=# CREATE table b(c1 int,c2 int)distributed by(c1);
CREATE TABLE

现在主要来看看跨库关联的两种情况:

— 情况一:a.c1=b.c2

即 a 表关联键是分布列,b 表不是。这种情况可以通过两种方法来实现表的关联:
1、重分布:将 b 表按照 c2 字段将数据重新分布到每个节点上,然后再和 a 表关联。这种情况下重分布的数据量就是 b 表的数据量 N;
2、广播:将 a 表上的数据进行广播,即每个节点都放一份全量数据,然后再和 b 表关联。这种情况下数据量大小就是 a 表数据量 M * 节点数 L。

综上,我们可以得出结论:
N > M L:选择广播;
N < =M 
L:选择重分布。

下面用实例来验证下:
—M = 20000,N = 15000,L=2:

postgres=# insert into a select generate_series(1,20000),generate_series(1,20000);
INSERT 0 20000
postgres=# insert into b select generate_series(1,15000),generate_series(1,15000);
INSERT 0 15000

— 执行计划:重分布

postgres=# EXPLAIN select * from a,b where a.c1=b.c2;
QUERY PLAN
---------------------------------------------------------------------------------------------------------
Gather Motion 2:1 (slice2; segments: 2) (cost=655.50..1117.00 rows=15000 width=16)
-> Hash Join (cost=655.50..1117.00 rows=7500 width=16)
Hash Cond: a.c1 = b.c2
-> Seq Scan on a (cost=0.00..224.00 rows=10000 width=8)
-> Hash (cost=468.00..468.00 rows=7500 width=8)
-> Redistribute Motion 2:2 (slice1; segments: 2) (cost=0.00..468.00 rows=7500 width=8)
Hash Key: b.c2
-> Seq Scan on b (cost=0.00..168.00 rows=7500 width=8)
Optimizer status: legacy query optimizer
(9 rows)

—M = 1000,N = 15000,L=2:

postgres=# TRUNCATE a
TRUNCATE TABLE
postgres=# insert into a select generate_series(1,1000),generate_series(1,1000);
INSERT 0 1000

— 执行计划:广播

postgres=# EXPLAIN select * from a,b where a.c1=b.c2;
QUERY PLAN
-----------------------------------------------------------------------------------------------------
Gather Motion 2:1 (slice2; segments: 2) (cost=67.00..287.50 rows=1000 width=16)
-> Hash Join (cost=67.00..287.50 rows=500 width=16)
Hash Cond: b.c2 = a.c1
-> Seq Scan on b (cost=0.00..168.00 rows=7500 width=8)
-> Hash (cost=42.00..42.00 rows=1000 width=8)
-> Broadcast Motion 2:2 (slice1; segments: 2) (cost=0.00..42.00 rows=1000 width=8)
-> Seq Scan on a (cost=0.00..12.00 rows=500 width=8)
Optimizer status: legacy query optimizer
(8 rows)

— 情况二:a.c2=b.c2

即两表的关联键都不是分布键,这种情况也分两种方法:
1、重分布:将表 a 和表 b 均按照 c2 列,将数据重分布到每个节点上,所以代价就是表 a 数据量 M + 表 b 数据量 N;
2、广播:将数据量较少的表数据进行广播,因此代价就是 min (M,N) 节点数 L。
综上,我们又可以得出此情况下的结论:
M + N > min(M,N) 
L:广播;
M + N <= min (M,N) * L:重分布。

—M = 15000,N = 15000,L=2:

postgres=# insert into b select generate_series(1,15000),generate_series(1,15000);
INSERT 0 15000
postgres=# insert into a select generate_series(1,15000),generate_series(1,15000);
INSERT 0 15000

— 执行计划:重分布

postgres=# EXPLAIN select * from a,b where a.c2 = b.c2;
QUERY PLAN
---------------------------------------------------------------------------------------------------------
Gather Motion 2:1 (slice3; segments: 2) (cost=655.50..1348.50 rows=15000 width=16)
-> Hash Join (cost=655.50..1348.50 rows=7500 width=16)
Hash Cond: a.c2 = b.c2
-> Redistribute Motion 2:2 (slice1; segments: 2) (cost=0.00..468.00 rows=7500 width=8)
Hash Key: a.c2
-> Seq Scan on a (cost=0.00..168.00 rows=7500 width=8)
-> Hash (cost=468.00..468.00 rows=7500 width=8)
-> Redistribute Motion 2:2 (slice2; segments: 2) (cost=0.00..468.00 rows=7500 width=8)
Hash Key: b.c2
-> Seq Scan on b (cost=0.00..168.00 rows=7500 width=8)
Optimizer status: legacy query optimizer
(11 rows)

—M = 1000,N = 15000,L=2:

postgres=# TRUNCATE a;
TRUNCATE TABLE
postgres=# insert into a select generate_series(1,1000),generate_series(1,1000);
INSERT 0 1000
postgres=# ANALYZE a;
ANALYZE

— 执行计划:广播

postgres=# EXPLAIN select * from a,b where a.c2 = b.c2;
QUERY PLAN
-----------------------------------------------------------------------------------------------------
Gather Motion 2:1 (slice2; segments: 2) (cost=67.00..287.50 rows=1000 width=16)
-> Hash Join (cost=67.00..287.50 rows=500 width=16)
Hash Cond: b.c2 = a.c2
-> Seq Scan on b (cost=0.00..168.00 rows=7500 width=8)
-> Hash (cost=42.00..42.00 rows=1000 width=8)
-> Broadcast Motion 2:2 (slice1; segments: 2) (cost=0.00..42.00 rows=1000 width=8)
-> Seq Scan on a (cost=0.00..12.00 rows=500 width=8)
Optimizer status: legacy query optimizer
(8 rows)

总结:

当表的分布式关联涉及到关联键不是分布列的时候,就会出现表的广播和重分布:

1、部分表的关联键不是分布列:N > M * L 则使用广播,反之使用重分布;

2、所有表的关联键都不是分布列:M + N > min (M,N) * L 则使用广播,反之使用重分布。 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值