1、GreenPlum这种share nothing的架构:

GreenPlum的并行查询优化策略  _GreenPlum的并行查询优化策略


良好的发挥了廉价PC的作用。自此I/O不在是DW的瓶颈,相反网络的压力会大很多。但是greenplum的查询优化策略能够避免尽量少的网络交换。对于初次接触greenplum的人来说,肯定耳目一新。


2、greenplum的查询优化器


greenplum的查询优化器负责将SQL解析成每个节点(segments)所要走的物理执行计划。也是基于成本的优化策略:评估若干个执行计划,找出最有效率的一个。主节点master负责SQL解析和执行计划的生成。

不像传统的查询优化器,Greenplum的查询优化器必须全局的考虑整个集群,在每个候选的执行计划中考虑到节点间移动数据的开销。一旦执行计划确定,比如有join,那么join是在各个节点分别进行的(本机只和本机的数据join)。所以它的查询很快。


3、查询计划包括了一些传统的操作,比如:扫描、Join、排序、聚合等等。greenplum中有三种数据的移动操作:


A: Broadcast Motion (N:N) ,即广播数据,每个节点向其他节点广播需要发送的数据。

B: Redistribute Motion (N:N) ,重新分布数据,利用join的列值hash不同,将筛选后的数据在其他segment重新分布。

C: Gather Motion (N:1),聚合汇总数据,每个节点将join后的数据发到一个单节点上,通常是发到主节点master。


4、一个简单的例子:


Sql代码
  1. explain select d.*,j.customer_id from data d join jd1 j on d.partner_id=j.partner_id where j.gmt_modified> current_date -80;

  2. QUERY PLAN

  3. ----------------------------------------------------------------------------------------

  4. Gather Motion 88:1 (slice2) (cost=3.01..939.49 rows=2717 width=59)

  5. -> Hash Join (cost=3.01..939.49 rows=2717 width=59)

  6. Hash Cond: d.partner_id::text = j.partner_id::text

  7. -> Seq Scan on data d (cost=0.00..260.74 rows=20374 width=50)

  8. -> Hash (cost=1.91..1.91 rows=88 width=26)

  9. -> Broadcast Motion 88:88 (slice1) (cost=0.00..1.91 rows=88 width=26)

  10. -> Seq Scan on jd1 j (cost=0.00..1.02 rows=1 width=26)

  11. Filter: gmt_modified > ('now'::text::date - 80)



执行计划执行从下至上:


a, 在各个节点扫描自己的jd1表数据,按照条件过滤生成数据rs

b, 各节点将自己生成的rs依次发送到其他节点。(Broadcast Motion (N:N) ,即广播数据)

c, 每个节点上的data表的数据,和各自节点上收到的rs进行join。这样就保证本机上的数据只和本机的数据join

d,各节点将join后的结果发送给masterGather Motion (N:1)



由上面的执行过程可以看出, Greenplum 是将 rs 给每个含有 data 表数据的节点都发了一份的。


要是 RS 很大或者压根就没有过滤条件怎么办呢:


Sql代码
  1. => selectcount(*) from jd1;

  2. count

  3. -------

  4. 20

  5. (1 row)

Sql代码
  1. => selectcount(*) from data;

  2. count

  3. --------

  4. 113367

要是 rs 很大的话,广播数据 网络就会成为瓶颈。可以看出 greenplum 很聪明:

它是将小表广播到各个 segment 上。可以看出统计信息对于生成好的查询计划是何等重要。


5、下面看一个复杂点的例子:

GreenPlum的并行查询优化策略  _GreenPlum的并行查询优化策略  _02


执行计划:


GreenPlum的并行查询优化策略  _GreenPlum的并行查询优化策略  _03

A,各个节点上 同时扫描各自的nation表数据,将各segment上的nation数据向其他节点广播(Broadcast Motion (N:N) )

B, 各个节点上 同时扫描各自customer数据,和收到的nation数据join 生成RS-CN

C,各个segment同时扫描自己orders表数据,过滤数据生成RS-O

D, 各个segment同时扫描 自己lineitem表数据,过滤生成RS-L

E,各个segment同时将各自RS-O和RS-L进行join 生成RS-OL,注意此过程不需要Redistribute Motion (N:N) ,重新分布数据,因为orders和lineitem的distribute column都是orderkey。这就保证了各自需要join的对象都是在各自的机器上,所以n个节点就开始并行join了。

F, 各个节点将自己在步骤E生成的RS-OL按照cust-key在所有节点间重新分布数据(Redistribute Motion (N:N),可以按照hash和range在节点间来重新分布数据,默认是hash ),这样每个节点都会有自己的RS-OL

G, 各个节点将自己在步骤B生成的RS-CN和自己节点上的RS-OL数据进行join,又是本机只和本机的数据进行join

H, 聚合,排序,发往主节点master

6、总结:


Greenplum如何处理和优化一张大表和小表的join?

Greenplum是选择将小表广播数据,而不是将大表广播。


举例说明:表A 有10亿 (empno<pk>,deptno,ename),表B(deptno<pk>,dname,loc) 500条 join on deptno

有11个节点:1 master+10 segment


按照正常的主键列hash分布,每个segment节点上只会有1/10的A和1/10的表B。


此时greenplum会让所有节点给其他节点发送各自所拥有的小表(B)1/10的数据,这样就保证了10个节点上,每个节点都有一份完整的表B的数据。此时 每个节点上1/10的A 只要和自己节点上的B进行Join 就OK。所以Greenplum并行处理能力惊人的原因就在这里。


最终所有节点会将join的结果都发给主节点master,master负责和各种client(比如JDBC,GP client等等)的连接。可见统计信息十分重要,Greenplum通过统计信息来确定将哪张表进行(Broadcast Motion (N:N) ,即广播数据)。

还有一种,对于列值倾斜的情况, 比如A 没有按照主键来hash分布,而是人为指定按照deptno的hash在各个节点上分布数据,若A中80%的数据 都是sales (deptno=10)部门的。此时10个节点中,就会有一个节点上拥有了10亿×80%的数据,就算是将B表广播到其他节点了 也无济于事,因为计算的压力都集中在一台机器了。所以选择合适的列进行hash分布,也很关键。