GreenPlum的并行查询优化策略

1、GreenPlum这种share nothing的架构:

GreenPlum的并行查询优化策略_第1张图片

 

    良好的发挥了廉价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 后的结果发送给 master  Gather Motion (N:1) 

 

 

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

 

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

 

Sql代码

  1. => select count(*) from jd1;   

  2.  count    

  3. -------   

  4.     20   

  5. (1 row)  

Sql代码

  1. => select count(*) from data;   

  2.  count     

  3. --------   

  4.  113367  

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

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

 

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

GreenPlum的并行查询优化策略_第2张图片

 

  执行计划:


 

GreenPlum的并行查询优化策略_第3张图片

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分布,也很关键。



你可能感兴趣的:(GreenPlum的并行查询优化策略)