ppg_fdw:如何使用pgsql构建mpp数据仓库(三)

   在简单描述了ppg_fdw的架构和工作流程之后,下面将会结合TPCH的实例来描述设计思想。
   前面已经提到TPCH是一个工业界认可的标准测试集合(包括数据和SQL的模板),主要用来测试OLAP系统的性能。用户可以用TPCH来生成测试的数据和SQL实例。TPCH的DW模型是一个典型的星座模型,其中lineitem和orders表示fact表,其余的6张表:customer nation part  partsupp region 和supplier,都可以看做dimension表。表之间通过外键进行关联,tpch的SQL实例中也反映了这一点。(一般来说,建模比较理想的DW之间的关联关系就应该这样清晰)
   在导入数据的时候,将dimension表导入到后台的OP的各个节点上,也就是完全复制。而对于fact表,则对fact表的主键按照范围进行水平分片,将各个水平分片导入到对应的OP上。数据的分部直接决定了最终的分布式查询计划,后面的例子会一再的说明这一点。
   在完成了数据的导入之后,下面就直接步入正题了。
   在TPCH的SQL模板中,一共有22个(本人使用了TPCH2_15,可能在各个版本之间有略微的差异)。TPC会根据这些模板来生成具体的实例。首先,对于这些SQL可以简单的分为两类:一类是只涉及dimension表的SQL,另外一类就是涉及到了fact表的SQL。对于只涉及dimension表的查询来说,处理比较简单,DQP可以直接选择一个后台的OP,直接转发给选定的后台OP,获得结果后DQP将结果返回给client。由于这些元数据的存储暂时还没有调研,并且查询的处理逻辑比较简单,这里就没有实现了,To Be Done。下面重点要说的就是对于涉及到fact表的SQL的查询处理。主要内容包括对agg的处理,join的处理,子查询的处理和order by和limit的处理。
   
    首先从最简单的开始,TPCH的模板6比较简单,生成的SQL实例如下:
  
   select
        sum(l_extendedprice * l_discount) as revenue
   from
        lineitem
   where
        l_shipdate >= date '1997-01-01'
        and l_shipdate < date '1997-01-01' + interval '1' year
        and l_discount between 0.06 - 0.01 and 0.06 + 0.01
        and l_quantity < 25
   LIMIT 1;
   

   这条SQL比较简单,只是在lineitme上施加了若干简单过滤条件,然后再求一个sum,最后做一个limit。对于这个SQL, ppg_fdw的planner生成的查询计划如下:
       (limit)
          |
        (sum)
          |
      (foreign_scan)
    这个图可能过于简单,但是直接明了的说明了全局的执行plan。在DQP上,会从上到下使用经典的迭代器的模型来执行,plan的叶子节点是foreign_scan节点(foreign_scan实际上就是调用了我们上一篇里面提到、和scan相关的接口)。这个节点负责将OP上执行的局部计划以SQL的形式发送给后台的若干台OP,下推的SQL实际是:
  
   select
        sum(l_extendedprice * l_discount) 
   from
        lineitem
   where
        l_shipdate >= date '1997-01-01'
        and l_shipdate < date '1997-01-01' + interval '1' year
        and l_discount between 0.06 - 0.01 and 0.06 + 0.01
        and l_quantity < 25
   

    一般说来,我们希望将尽可能多的operator下推,在这里,我们实际下推了filter project 和agg。
    对于OLAP来说,agg是必须需要处理的。一般来说,对于agg来说,可以采用二次聚集的方式,就如上面简单的图示;或是直接的下推。如果agg存在group操作,且group所作用的字段组合前缀就是用来将表水平分片的字段,那么可以直接下推agg,否则需要做二次聚集,就如上所示。
    Agg的处理
    在这个例子中,sum的二次聚集在逻辑上可以简单的表示为sum(sum):外层的sum在DQP上执行,内层的sum则下推到OP执行。 和它类似的有min max和count:,而对于avg的二次聚集则相对麻烦一点,逻辑上表示为 sum(sum)/sum(count),可能画成图比较容易理解:
             / (除操作)
            /  \
         sum    sum
          /      \
        sum       count
    最下层的sum和count会直接下推到OP来执行,而在DQP上执行的是 sum count和/ 这三个操作。
    (如果agg的参数中含有disctinct,则处理比较简单,将distinct下推到OP,然后再做二次的distinct,TO BE DONE)

猜你喜欢

转载自scarbrofair.iteye.com/blog/2162480