当前位置: 首页 > 科技观察

Join优化技术之RuntimeFilter

时间:2023-03-13 19:13:07 科技观察

1.BackgroundRuntimeFilter也叫DynamicFilter。其目的是在join的探测端提前过滤掉不会命中join的输入数据,大大减少join中的数据传输和计算,从而减少整体执行时间。简单来说,就是利用小表的joinkey,根据大表的joinkey构造过滤器,减少大表的数据读取。图中左侧为普通扫描查询计划,右侧为添加运行时过滤器(DynamicFilter)后的扫描计划。可以看到probe端在Join之前(Scan期间)提前过滤掉了数据。SELECT*fromfact_tableAJOINdimension_tableBWHEREA.join_key=B.join_key;但实现层面的难点在于如何将数据从RuntimeFilter(DynamicFilter)Builder端转发到probe端,因为这些算子可能运行在不同的节点上。一般有以下几种设计方案:Coordinator(Remote模式)Local模式2.ImpalaVSPresto2.1ImpalaImpala采用这两种方式,Presto采用Local模式。ImpalaRemote方式Impalalocal是指生成的RF可以直接应用,无需网络传输。一个典型的例子,当BROADCASTHASHJOIN时,左表的JOIN和HDFSTableScan是在一个Fragment中(在一个线程中)实现的。运行在每个节点上的JOIN会得到右表中的所有数据,因此可以根据右表中的数据构建完整的RF信息,然后将这些信息直接传递给左表中的Scan算子,而不需要经过任何网络传输。RuntimeFilter的实现层面采用了BloomFilter。上图中,各个节点从HDFS读取数据,然后传输到JoinNode,最后到达协调器,统一合并后分发数据。2.2Prestopresto本地模式Presto的DynamicFilter包括PartitionPruning(分区表)和Row过滤(非分区表),依赖于broadcastjoin,builder端的table比probe端的表小很多。在这种情况下,探测端扫描和连接运算符在同一个进程中运行——因此它们之间的消息传递变得更简单。Presto将生成的DynamicFilter作为TupleDomain暴露给Probe端的PageSourceProvider。TPC-DS运行结果表明,DF在某些查询、基于成本的优化器(CBO)上具有显着优势。Presto的实现原理:DynamicFilterDynamicFilterSourceDynamicFilter代表了计划的一部分,一旦过滤数据准备好,就会在运行时执行真正的过滤。DynamicFilterSource负责构建运行时谓词数据(例如Bloom过滤器)并在准备就绪时将其传递给DynamicFilter。除了构建布隆过滤器DynamicFilterSource节点外,它还充当传递节点,将接收到的数据转发到Join节点。代码实现视角:DynamicFilterSource运算符在保存输入页面信息时充当简单的“传递”管道。收集的页面值用于创建RunTimeFilter约束(用于内部连接中的探测端表扫描)。请注意,此运算符仅支持小型表构建器端页面(使用“广播”连接时应该是这种情况)。下图中的红色箭头表示发送谓词(如布隆过滤器)时的通信。这里可以使用标准的Presto数据通信方式(PagesoverExchanges)将数据从DFS传输到DF。实施另一个“元数据”协议似乎过于复杂。如果您将此连接公开为直接的父子关系,因为这将导致计划不再是一棵树,而是一个DAG。这将破坏(或至少使)访问者的当前遍历方法。无论如何,在优化期间围绕计划树移动一个或另一个时,需要保留DFS到DF的关系。因此,最终的实现方式是提供一个DynamicFilterSource操作符作为通信通道。https://varada.io/blog/presto/dynamic-filtering-for-highly-selective-join-optimization/https://github.com/prestodb/presto/pull/9453/commits