use*_*815 3 apache-spark apache-spark-sql
我正在尝试了解 spark 3 中的新功能:动态分区修剪。
看看这个测试:
我不明白为什么它是动态的和经典的修剪?
谢谢
随着 Spark 3.0 的发布,实现了重大改进以使 Spark 执行得更快,并且随之而来的是许多新功能。其中,动态分区剪枝就是其中之一。在深入了解动态分区修剪中的新功能之前,让我们了解什么是分区修剪。
在标准数据库中,修剪意味着优化器将避免读取不能包含您正在查找的数据的文件。例如,
select * from Students where subject = ‘English’;
Run Code Online (Sandbox Code Playgroud)
在这个简单的查询中,我们试图匹配和识别学生表中属于学科英语的记录。这转化为一种简单的形式,即扫描顶部的过滤器,这意味着首先扫描整个数据,然后根据条件过滤掉。
现在大多数查询优化器都尝试将过滤器从扫描的顶部向下推到尽可能靠近数据源的位置,以避免扫描整个数据集。
在分区剪枝技术中,它遵循过滤器下推方法并对数据集进行分区。因为在这种情况下,如果您的查询在分区列上有一个过滤器,您实际上可以跳过完整的分区文件集。
Spark 中的分区修剪是一种性能优化,它限制了 Spark 在查询时读取的文件和分区的数量。对数据进行分区后,匹配特定分区过滤条件的查询通过允许 Spark 仅读取目录和文件的子集来提高性能。当存在分配过滤器时,催化剂优化器会向下推分配过滤器。扫描仅读取与分区过滤器匹配的目录,从而减少磁盘 I/O。
然而,实际上数据工程师在他们的查询中不只是执行单个查询或单个过滤器,常见的情况是他们实际上有维度表,他们需要与更大的事实表连接的小表。因此,在这种情况下,我们不能再应用静态分区修剪,因为过滤器位于连接的一侧,而对修剪更有吸引力且更有吸引力的表位于连接的另一侧。所以我们现在有一个问题。
select * from Students join DailyRoutine
where DailyRoutine.subject = ‘English’;
Run Code Online (Sandbox Code Playgroud)
有些人可能会建议我们可以预先将维度表与事实表连接起来。通过这种方式,我们仍然可以触发对单个表的静态修剪。然后他们可以在单独的查询中执行他们的过滤器,如下所示。
这种方法有明显的缺点,因为首先我们必须执行这个非常昂贵的连接。我们正在复制数据,因为我们必须生成另一个中间表。这张桌子可能很宽,因为我们将一堆小桌子与一张大桌子连接在一起。不仅它很宽,而且在更新维度表时实际上非常难以管理。因此,每当我们进行更改时,我们实际上都必须重新触发整个管道。
在这个博客中,我们将学习一种完全不同的方法,我们将使用动态修剪进行过滤。这种优化的基本目标是能够从维度表中获取过滤结果。然后直接使用它们来限制我们将从事实表中获取的数据。
在 Spark SQL 中,用户通常使用他们喜欢的编程语言从他们喜欢的 API 提交他们的查询,因此我们有数据框和数据集。Spark 接受此查询并将其转换为可理解的形式,我们称之为查询的逻辑计划。在此阶段,spark 通过应用一组基于规则的转换(例如列修剪、常量折叠、过滤器下推)来优化逻辑计划。只有稍后,它才会进行查询的实际物理规划。在物理规划阶段,spark 生成一个可执行的计划。该计划将计算分布在多台机器的集群中。在这里,我将解释如何在逻辑规划级别实现动态分区修剪。然后我们将研究如何在物理规划期间进一步优化它。
让我们从逻辑规划级别的优化机会开始。让我们考虑一个跨多个文件分区的数据集。每个分区都会因特定颜色而有所不同。另一方面,我们将有一个较小的表,它是一个不一定分区的维度表。然后我们在这些数据集之上有典型的扫描操作符。每当我们过滤维度表时,请考虑一个示例,其中只有对应于连接另一侧的两个分区的行实际上是相关的。所以当我们完成最后的 join 操作时,实际上只有这两个分区会被 join 保留。
因此我们不需要实际扫描完整的事实表,因为我们只对维度表产生的两个过滤分区感兴趣。为避免这种情况,一个简单的方法是将维度表中的过滤器合并到子查询中。然后在事实表上的扫描下方运行该子查询。
通过这种方式,我们可以在计划联接的事实方面时弄清楚这一点。我们能够确定这个连接需要哪些数据。这是一个简单的方法。
但实际上它可能很昂贵。我们需要摆脱这种重复的子查询,并找出一种更有效的方法。为了做到这一点,我们将看看 spark 如何在物理规划期间执行连接,以及 spark 如何在此物理规划阶段转换查询。
如果维度表很小,那么spark 很可能会将连接作为广播散列连接来执行。每当我们有两个散列连接的表时,就会发生许多事情-
现在这两个阶段之间显然存在着天然的屏障。所以首先我们要计算连接的广播端。我们正在分发它,然后才开始探测和执行实际的连接。这非常有趣,我们希望能够将其用于我们的优化。因为这正是我们在子查询的逻辑规划级别上所模仿的。
所以这就是我们实际要做的。我们正在截取构建端的结果——广播结果。我们将直接获取它们并将它们作为动态过滤器插入到事实表顶部的扫描器中。所以这实际上是动态分区修剪的一个非常有效和优化的版本。
总而言之,在 Apache sparks 3.0 中,实现了一种称为动态分区修剪的新优化,它适用于:
我希望这个答案有帮助!
| 归档时间: |
|
| 查看次数: |
644 次 |
| 最近记录: |