6月22日至27日,2025 ACM SIGMOD/PODS国际学术会议在德国柏林举行。25日,华为多伦多分布式调度和数据引擎实验室主任工程师 Timothy Zeyl受邀出席,就入选的《Including Bloom Filters in Bottom-up Optimization》论文进行了解读
该论文创新性地首次提出了在自下而上的优化器的基于成本的优化过程中添加布隆过滤器(Bloom Filter)的技术。该技术可以在关系型数据库进行复杂查询处理过程中生成更优的查询计划,从而提高系统查询性能,优化用户使用体验,并且适用于所有的查询类型。
本篇文章将对该论文进行详细解读,解锁在自下而上的查询优化中添加布隆过滤器的奥秘。
1.背景介绍
布隆过滤器是一种众所周知的数据结构,可用于关系型数据查询处理中对表的早期过滤。通过这种方式,可以显著减少在查询树的更高层级处理的行数(即由下游操作符处理)。如果在计划期间加以应用,可以得出更好的SQL查询计划,从而提高查询性能。
然而,目前只有在自上而下的级联式 (Cascades) 优化器中,才会在成本估算期间考虑布隆过滤器,还有很大一类SQL数据库系统 (GaussDB、Oracle、DB2、PostgreSQL、MySQL等) 采用的是自下而上的查询优化方式(相对于自上而下)。在这些自下而上的优化器中,由于布隆过滤器是在查询计划已经确定之后才添加的,使得可能存在的更好的查询计划未被使用。
该论文首次提出了如何在自下而上的优化器的基于成本的优化过程中添加布隆过滤器,面临的挑战、创新解决方案以及成果。
2.关键挑战
在成本计算中添加布隆过滤器主要面临着两大挑战:
一、在自下而上的优化过程中添加布隆过滤器,会增加需要评估的子计划组合数量,从而导致优化时间变长,而优化耗时带来的弊端可能会超过找到更快的查询执行计划所带来的收益,尤其是对于运行时间较短的查询。
二、布隆过滤器的过滤量取决于其在查询树中构建的位置,以及出现在构建位置下方的表的具体组合情况。
例如,如果我们在哈希连接 (Hash Join) 中构建一个布隆过滤器,并且在构建侧(Build Side) 下方存在有损连接 (Lossy Join),那么与构建侧下方是无损连接(lossless Join)(或无连接)的情况相比,该布隆过滤器有可能过滤掉更多的行,如图:
因此,在使用布隆过滤器时,需要根据其构建位置下方表或连接的情况来维护多个包含不同行数估计值的子计划 (Sub-plans)。然而,由于在自下而上构建计划时并无法预先确定下方会出现哪些表或连接,所以也无法提前预估布隆过滤器过滤的行数。
对此,有一个简单的解决方案——对所有未进行成本估算的布隆过滤器子计划都进行维护,也就是说对出现在布隆过滤器构建位置下方的每个表组合都创建一个子计划,然后将行数估计和成本估算一直推迟到评估所有所需表连接的解析结果时再进行。
但是,由于未进行成本估算的计划无法被裁剪(Prun),这种方案需要维护的连接路径的数量将呈指数级增长,这会导致优化时间非常长:
表1:连接查询优化耗时
3表连接查询优化时间 |
28毫秒 |
4表连接查询优化时间 |
375毫秒 |
5表连接查询优化时间 |
56秒 |
6表连接查询优化时间 |
30分钟仍未完成 |
3.技术创新
防止搜索空间呈指数级增长的关键在于推迟规划,直到进行裁剪操作。
该论文提出的技术创新是:将优化过程分为两个自下而上的阶段,在第二个自下而上构建计划阶段对所有布隆过滤器子计划进行完整的行数估计和成本估算。
第一阶段
-
自下而上地确定所有有效的连接组合。
-
估计每个连接结果的行数。
-
确定所有布隆过滤器的候选对象——可以应用布隆过滤器的表。
-
记录每个布隆过滤器候选对象在布隆过滤器构建侧所需的关系集。
在这个阶段,可以掌握充分的信息来全面预估所有应用了布隆过滤器的表扫描(即布隆过滤器子计划)的行数与成本。布隆过滤器子计划还会列出构建侧所需的表。在对布隆过滤器子计划进行连接组合时,这些表必须出现在哈希连接的内侧。
第二阶段
采用与常规自下而上优化器非常相似的方式来计算所有子计划的行数估计值和成本。
布隆过滤器子计划的行数比没有使用布隆过滤器的对应子计划的行数要少,且其额外的属性限制了它们可以与哪些其他子计划进行组合。这既确保了在对布隆过滤器子计划进行成本估算时所做的任何假设是有效的,同时也减少了搜索空间。
-
如果布隆过滤器子计划仍有要求某些关系出现在构建端(build side),那么这些子计划之间可以相互裁剪(prune)。
-
如果布隆过滤器子计划所需的构建端关系已经通过某个连接操作被解决(resolved),那么它们现在可以与任何其他子计划相互裁剪。并且,由于布隆过滤器子计划的行数较少,其已解决的子计划通常成本也会较低。
第一阶段因为实际上没有进行真正的优化,所以过程非常快。第二阶段添加了需要与其他子计划结合起来进行评估的额外的布隆过滤器子计划,这样既能对这些子计划进行全面的成本估算,也能对它们彼此之间、它们与其他不含布隆过滤器的子计划进行裁剪,如此便能避免上文提到的简单解决方案会发生的搜索空间激增的问题。
不过需要注意的是,与不用布隆过滤器进行成本估算的情况相比,还是需要探索更多的子计划。所以,仍然需要权衡额外优化耗时的成本与潜在更优查询计划的好处之间的利弊。对此,论文中提供了几种启发式方法来限制需要探索的子计划的数量。具体的启发式方法在这里不展开阐述,有兴趣的读者可以参阅原文。
当前,该技术已经集成到了华为云数据库GaussDB的优化器中。
4.结果验证
为了验证该方法的效果,论文展示了100GB的TPC-H数据集进行测试的结果。
结果显示,在所有的分析查询中,在计划后处理(BF-Post)中添加布隆过滤器,运行时间相对没有添加布隆过滤器减少了28.8%。而采用论文中的自下而上优化中添加布隆过滤器,运行时间减少了52.2%。与计划后处理(BF-Post)中添加布隆过滤器相比,在自下而上优化中添加布隆过滤器的运行时间减少了32.8%,因此在自下而上优化中添加布隆过滤器的效果是非常明显的。
表2:TPC-H查询延迟
5.总结
该论文描述了在自下而上的优化器中添加布隆过滤器的挑战和两阶段自下而上优化的解决方法。
该方法通过推迟子计划的规划和代价计算避免了不必要的搜索空间增长。尽管该方法会增加搜索空间,但也提出多种方法来进行控制。在TPC-H查询测试验证中,该方法可以让查询延迟相比于BF-POST方案进一步降低32.8%。
在自下而上优化中添加布隆过滤器为数据库领域提供了一个切实可行的方案,而这种优化器在许多商业和开源数据库中都有使用,对企业而言,则有助于生成更优的查询计划、缩短查询的运行时间,大幅度优化系统在数据查询处理时的性能,从而为企业带来更顺畅的使用体验。
作者简介
Timothy Zeyl,多伦多大学博士,华为多伦多分布式调度和数据引擎实验室主任工程师(Principal Engineer),于2016年加入华为。Timothy Zeyl曾参与运用机器学习在Presto、Spark和Hadoop等分布式系统中进行预测调度与准入控制等多个项目的研究,在基于RNN的时间序列预测和自适应准入控制机制方面作出了重要贡献。
Qi Cheng,华为多伦多分布式调度和数据引擎实验室杰出工程师(Distinguished Engineer),SQL优化器资深专家,该论文想法的主要提出者和重要参与者。Qi Cheng于2023年加入华为,深耕数据库领域30多年,在关系DBMS、分布式DBMS、嵌套关系DBMS、主存DBMS和面向对象DBMS等不同领域都有成熟的工作经验。