PgSQL内核特性 - push-based pipeline 执行引擎-PgSQL的pipeline执行引擎

时间:2024-02-21 16:31:01

GSoC 2017中有个改造pipeline的项目,基本思想是遍历执行计划树,找到叶子节点,从叶子节点开始获取数据,然后推送给各个父节点。

a5f26d7aae987eb5983308fe8bf162a6.png

执行器中,使用RunNode函数递归调用,得到叶子节点:先遍历右节点,然后再遍历左节点;当然若没有右节点,则直接遍历左节点;当没有左右子节点时,就到了叶子节点,那么通过pushTuple来推送数据。

20c4d9a62648ddac5a190030b6aaaf0f.png

pushTuple根据父节点类型调用各自推送函数,将数据推送给父节点,比如上面流程:当父节点是LimitState时,调用pushTupleToLimit进行推送。

我们看下SeqScan:其实就是从存储引擎获取数据,进行过滤和投影,然后根据父节点类型,推送给父节点。

pushTupleToSeqScan(SeqScanState *node)
  heappushtups(...,node->ss.ps.parent,node)
    |--  get a tuple in the page
      SeqPushHeapTuple(HeapTuple tuple, PlanState *node,SeqScanState *pusher)
      |--  slot = SeqStoreTuple(pusher, tuple);
      |--  ExecQual && ExecProject
      |--  return pushTuple(slot, node, (PlanState *) pusher);
        |--  if (!node){//pusher top level node, send to dest
            return SendReadyTuple(slot, pusher);
          }

对于hash join来说,需要先构建hash表,然后外表数据从hash表中进行探测;pipeline引擎中怎么推送完成hash join呢?

从RunNode函数中可以也可以看到,他是先从内表分支开始推送数据,推送给Hash节点构建hash表,然后推送给父节点。pushTuple函数中,当hash join的右分支推送上来时,pushTupleToHashJoinFromInner函数仅获取hash表,并不继续向上推送;而是HashJoin的左子分支推送上来的数据进入pushTupleToHashJoinFromOuter,进行hash探测,找到符合条件的数据,并向上层父节点推送join结果:

e851bc93932fa5917db0f59154604da2.png

可以得知,该改造并没有充分利用各个叶子分支并行,未来可以向整个方向进行优化。