Why openLooKeng?

跨数据中心数据分析

统一的SQL接口访问跨数据中心、跨云的数据源

极简的跨源数据分析体验

统一的SQL接口访问多种数据源

易扩展数据源

可以通过增加Connector来增加数据源

采集变连接、数据零搬迁

openLooKeng社区活力

贡献者

用户

社区会员

博客

  • 以openGauss Connector下推为例剖析Connector下推机制

    程一舰 | January 7, 2022

    作者简介:程一舰 中国人民大学硕士,中国光大银行总行信息科技部 一、下推是什么? 下推其实就是将查询中的谓词或算子尽可能地向查询计划树的叶子结点靠近,最理想的情况就是将谓词或算子下推至叶子结点,这样就意味着可以将它们推至数据源了,通过数据源的预处理,可以极大的减少引擎从数据源拉取的数据量,从而极大提高查询效率。最简单的如下图所示。之前我也写过一篇sparksql下推的文章,有兴趣可以去看一下https://mp.weixin.qq.com/s/NgrRuKUaVi-pknVnHcK32g。 二、openLookeng引擎的Connector下推 下面是一条SQL语句执行的各个环节,查询语句经过解析之后形成抽象语法树,然后经过Analyze生成逻辑计划,逻辑计划再通过一系列的优化规则来生成优化后的更高效的逻辑计划进而转成物理计划。而Connector下推就处于逻辑计划优化阶段的某一环节。 我们来看一下下面这张图,openLooKeng新下推框架的主要思想是把执行计划子树暴露给connector,让connector提供PlanOptimizers(基于visitor模式的)给执行优化引擎,这样可以让connector引入任意的优化。这张图展示了Connector下推在整个查询优化缓环节的位置,其实不难看出,真正触发这个过程的就是ApplyConnectorOptimization这条优化规则,它也仅仅是众多优化规则中的一条规则。只是这条规则会把关于该Connector相关的最大子查询计划(maxsubplan)推给Connector去优化,该Connector针对本数据源进行一系列的定制优化。 三、openGauss Connector下推优化实践 上面说了这么多,到底怎么来具体实现一个Connector的下推优化呢,我们接下来以openGauss Connector为例。这个Connector顾名思义,就是用来连接GaussDB数据库的,它本身继承或复用了postgresql和basejdbc的一些类,所以在进行下推实现的时候,我们也可以继续去复用一些类。 首先,我们从逻辑计划开始,LogicalPlanner类是对刚刚解析出来的抽象语法树(AST)进行逻辑计划生成的类,在生成逻辑计划的同时,他还会做一件很重要的事就是对逻辑计划进行优化,我们可以从222行看到,这里的planOptimizers包含了几十条优化规则,而我们上面提到的ApplyConnectorOptimization就在第55条规则中,当循环遍历到这条规则的时候,其实也就是Connector逻辑优化的开始了。 然后,就如上面我所介绍的,当遍历到ApplyConnectorOptimization规则的时候,就会调用对应的Connector 的 Optimizer,在这里我们可以清晰地看到,因为我查询的catalog是一个GaussDB表,所以这个Optimizer就是JdbcPlanOptimizer(按理说应该是opengaussPlanOptimizer,但是上面说到过,因为openGauss Connector很多功能都是复用了Jdbc,这里也不意外),这个优化器中包含的一个比较重要的成员变量就是queryGenerator,因为正是通过他来进行后续的sql语句的生成。这里我们可以看到这个具体的Generator是opengaussQueryGenerator,为了方便,在具体实现这个类的时候,里面也是复用了BaseJdbcQueryGenerator类中的内容。 那接下来我们就看看JdbcPlanOptimizer做了哪些具体的优化。首先我们看到它会调用自己的optimize方法,来对推下来的maxSubPlan进行优化,具体的执行就通过调用accept方法来调用Visitor这个类来进行具体的节点遍历。 然后就是通过调用visitPlan来进行算子的转换,如下图就是主备对聚合算子AggregationNode进行相关操作。 tryCreatingNewScanNode会调用queryGenerator对象来进行算子的重写(其实就是把能推下去的通过重写SQL的方式把该算子加进去)。 我们看到这里开始准备重写,就进入到了BaseJdbcQueryGenerator类中来了(其实是进入到了openGaussQueryGenerator类,只是我复用了BaseJdbc,所以最后实在这里来做的),这里是调用的visitAggregation方法,主要就是来进行聚合算子的提取工作, 进一步,buildSql方法顾名思义,将提取出来的算子进行推到重写的SQL中,如下所示 最后重写完成,又回到了JdbcPlanOptimizer进行下一步的操作。毕竟优化器只是将子计划进行重新优化,所以最后还是要返回一个PlanNode的,所以我们看到接下来我们在上面重写的sql会被用来进行封装,最后封装成了TableScanNode里被返回。 其实到了这里就已经完成了具体的opengauss Connector的下推了,但是我们如果跳出来,看看它在整个执行过程中的位置,回想一下前面我们提到的,这也仅仅是我们完成了ApplyConnectorOptimization这一条优化规则的任务,如果你忘了我再重新贴一下图。 所以接下来,还会把我们刚刚返回的封装好的子查询计划继续应用其他规则。 再往后,引擎其实还会在全局的角度对整个查询进行一个重写,也就是在BaseJdbcClient这里所做的。 这里会通过QueryBuilder来重新梳理出一条sql语句,最终推给数据源。如下图所示,其实我们前面做的那么多,在全局看来只是一个table,别名为pushdown。 这里再次重写完的SQL,其实就是最终我们推给数据源执行的SQL了。 四、优化效果 通过查看执行计划,我们来看(下推)优化与不优化的效果对比。 即使不标明,我相信你也应该能看出哪一个是进行优化的效果了。第一张图片,我们可以看到正常情况下会从数据源读取数据,然后进行过滤、聚合、shuffle再聚合,而第二张图片我们看到Connector直接将条件和聚合算子推给了数据源,最后只接收一个聚合结果,从而大大解放了Connector,减少了数据的传输等效率损耗,从而提高查询性能。 五、总结 通过本篇文章,我相信你已经大致对Connecor下推以及查询下推的原理有了一个比较形象的了解了,如果你想继续深入了解,可以再次按照这个思路去捋一捋源码,其他情况的话,相信这篇文章已经足够能够解答你的疑惑了。opengauss connector下推的PR我已经提到社区了https://gitee.com/openlookeng/hetu-core/pulls/1354,欢迎交流。

  • openLooKeng 基于选择率的动态过滤优化

    李铮 | December 31, 2021

    1 概述 如之前openLooKeng博客中所述,动态过滤的核心思想是依靠join条件以及build侧表读出的数据,运行时生成动态过滤条件(dynamic filters),应用到probe侧表的table scan阶段,从而减少参与join操作的数据量,有效地减少IO读取与网络传输。动态过滤优化方法包含4个主要阶段: partial filters的构建,partial filters合并,partial filters以及merged filters的传输,merged filters应用。 动态过滤特性系统架构如下图所示,总体架构来看,在进行join处理时,对物理执行计划进行改写,添加DynamicFilterSourceOperator,进行join时build侧表的数据收集。之后,将收集到的partial filters包装成bloomfilter发送给分布式缓存hezelcast。与此同时,构建DynamicFilterService,对收集到的partial filters进行合并。在合并完成之后,将生成好的dynamic filter推给join时probe表,作为其额外的过滤条件,在table scan时对数据进行过滤。 通常场景下,所有的join node都会生成dynamic filter,然后依靠优化器规则PredicatePushDown将生成的dynamic filter下推给TableScanNode。然而,默认的动态过滤生成与应用缺乏对于元数据信息的感知,查询分析引擎probe侧表的filter需要等待build侧表读取完成之后生成,默认join结点的probe表的读取会首先等待一个时间(如1000ms),如果没有等待到build侧的filter传入则无法利用。如果build过滤后的数据量相对大时,也会导致大量的filter在网络中传输。总的来说,直接利用join进行动态过滤生成与应用,缺乏利用统计信息以及元数据信息对于动态过滤条件生成及应用进行预估,导致选择率很低的动态过滤条件生成与使用,造成额外的系统开销。 2 动态过滤优化 2.1 基于选择率优化 当前,优化器规则中RemoveUnsupportedDynamicFilters仅仅删除那些不应该存在的动态过滤条件,比如build侧存在的动态过滤条件或者是probe侧存在动态过滤条件但是对应的JoinNode中并不存在。因此,这个规则是无法支撑我们基于元数据和CBO进行动态过滤生成与应用调整的。因此,我们需要扩展RemoveUnsupportedDynamicFilters规则: 将Metadata以及cost provider提供给RemoveUnsupportedDynamicFilters 删除我们不需要的动态过滤条件,例如,如果表很小且动态过滤无法帮助过滤,那么表应该被过滤得足够多,我们不需要启用动态过滤。 2.2 动态过滤条件生成优化 此外,openLooKeng早期版本,对于动态过滤条件的合并与生成,是为每一个DynamicFilterSourceOperator都注册一个driver id。如果DynamicFilterSourceOperator快速的完成,那么刚注册了他的driver id就很快完成,那么在coordinator上的DynamicFilterService可能会错误的以为所有worker已经完成了自身的读取任务,可以合并动态过滤条件生成最终的数据,这可能会导致错误的结果。此外,对于每个查询,与coordinator中hazelcast的交互次数为 num(Dynamic Filter) * num(Worker) * num(DynamicFilterSourceOperator per Worker) * 4(register, finish, worker, partial result) 当部署到具有高并发查询的大群集时,这可能会意味着coordinator需要为每个DynamicFilterSourceOperator执行合并,可能造成极大的网络传输数据量以及计算开销。为了解决这个问题,openLooKeng 1.1.0中在每个任务中由各个worker完成自己持有的动态过滤条件的合并。因此,DynamicFilterService只需要合并每个worker提供的过滤条件。 2.3 基本实现原理 在RemoveUnsupportedDynamicFilters的优化器中,在进行动态过滤条件检验时: 检查build侧表的预估输出行大小,并且丢弃可能会比较大的动态过滤条件(handleTooLargePredicate()方法仍将保留在DynamicFilterSourceOperator中作为保护措施)。 计算build侧的选择率,如果发现build侧的表的本身自带的过滤条件无法很好的过滤数据,即基本是全表扫描,那我们将对该build侧的表参与的JoinNode中的动态过滤条件删除。 如下图所示,红色框标记的参与join计算的build侧的表,其本身行数过大或者是全表扫描,那么就不会针对该JoinNode生成并应用动态过滤。 另外一种场景,对于tpcds q2,执行计划如下图所示。实际上,DF-3可以过滤顶部JoinNode的probe侧的表。但是由于pipeline调度的关系,因为我们配置了hivePageSouce等待时间,所以整个subplan的执行必须等待右侧的subplan完成。因此,我们可以删除DF-3,对于底部表A,可以尽快获得动态过滤条件,对于表B扫描,它可以使用表A中的动态过滤条件。由于整个左子树可以更早地利用动态过滤,语句整体的执行时间因此缩短。 对于动态过滤条件生成,我们会将每个worker负责的partial动态过滤条件在LocalDynamicFilter:addOperatorResult()中进行合并,当所有分区的读取完成之后,worker将把合并后的partial filters放入到hazelcast当中。相对应的,DynamicFilterService中的逻辑也可以简化,我们只需要检查所有参与的worker是否完成了他们自己的任务,并将最终合并后的partial filters放入到了hazelcast中。因此,我们不再需要维护复杂的状态信息,因为coordinator参与处理的worker总数,其处理逻辑也得到很大的简化。

更多...

新闻

  • openLooKeng v1.5.0 正式发布

    openLooKeng | December 30, 2021

    openLooKeng社区用户数达到 100K +,累计收到 2000+ PR,1500+ Issue,1500+ Comments,2021年,社区下载量突破 100K +;遍及全球41个国家、210个城市。越来越多的人关注到openLooKeng,如今,社区呈现一派生机勃勃,绿荫环绕的景象。

  • 2021信创“大比武”鲲鹏赛道总决赛圆满落幕,openLooKeng两支队伍获奖

    openLooKeng | November 29, 2021

    信创“大比武”总决赛圆满落幕,全国十强队伍上线,参与openLooKeng赛题的两支队伍,北明大数据团队与鸿鹄团队分别荣获铜奖与优胜奖。恭喜!

更多...