前言Spark SQL是Spark中一个极为重要的模块,主要用于结构化数据分析处理,Catalyst是Spark SQL的底层核心,由于它涉及的范围比较广,一篇文章无法讲解它所有的知识,因此本文仅介绍queryexecute类,它封装了Catalyst用于执行查询流程中涉及的每个主要阶段的方法,这些方法是惰性方法,仅在触发要查询的数据集的操作时才执行。如下图所示,queryexecute类将整个Spark SQL执行流程都串联起来:
在本文的其余部分主要讨论queryexecute类,并以宏观的视角讲解查询执行中涉及的每个阶段,此外,通过使用一个查询示例来解释查询执行流程,从文本SQL语句到解析、分析、优化,再到物理计划。此示例查询用于从Databricks示例数据集查询数据,该数据集将 'sales' 表联接到 'items' 表,并选择 'i_price'列值小于10的项。
SQL解析(SQL Parsing) Catalyst中查询计划的内部数据结构是通过每个阶段的规则进行转换的树。首先需要将文本格式的输入SQL语句解析为树类型。在调用Spark Session的SQL方法时,SQL解析器首先将sql语句解析为ANTLR ParseTree,然后将ANTLR ParseTree转换为未解析的逻辑计划。然后将未解析的逻辑计划传递到数据集的ofRows方法中以创建queryexecute实例。
对于我们的sql示例,这是从我们的sql语句解析的未解析逻辑计划。如你所见,“sales” 表和 “items” 表均未解决。未验证列名,列上没有类型信息。SQL分析(Analysis) Spark SQL Catalyst提供了一个逻辑查询计划分析器,该分析器从SessionCatalog检索表和属性信息,并将未解析的数据属性和未解析的关系转换为完全类型的对象。SessionCatalog是底层元存储 (如Hive元存储) 的代理。数据存储是一个重要的话题,我将只写一篇博客文章来报道Hive数据存储。现在,你可以认为在元存储中可以查找表和列的完整类型信息。根据Databricks发布论文:“Spark SQL: Relational Data Processing in Spark”(文末附论文获取方式),逻辑查询计划分析器在分析阶段执行以下操作:
- 按名称在SessionCatalog中查找关系
- 映射命名属性,如列名
- 确定具有相同值的属性并提供唯一id
- 通过表达式传播和强迫类型
回到我们的示例,在分析了未解决的逻辑计划之后,我们得到了以下已分析的逻辑计划。如你所见,逻辑计划现在知道关系的全名和文件格式。可以识别列的数据类型,并且每个列都关联了唯一的id。逻辑优化(Logical Optimisation) 在分析逻辑计划之后,逻辑计划优化器将基于规则的标准优化应用于逻辑计划。Catalyst附带了大约70个预构建的逻辑计划优化规则,每个规则都将结构化查询的一部分的查询计划转换为优化的逻辑计划,并在规则批处理中执行。在我们的例子中,PushDownPredicate规则应用于分析的逻辑计划,并将过滤器从 “之后联接操作” 移动到 “之前联接操作” 和 “数据加载” 之后。这种优化有望减少要加入的数据集的大小,并确保在物理计划阶段将谓词向下推到数据源。
物理计划(Physical Planning) 逻辑计划独立于平台,无法由Spark解释和执行。Spakerplan需要将逻辑计划转换为SparkPlan。Queryexecute提供了一个createSparkPlan方法,该方法将优化的逻辑计划作为输入并调用计划Sparkplan的方法,该方法应用节点匹配策略来返回候选物理计划列表。
基于成本的模式有望分析每个候选物理计划的成本并选择最佳计划。对于Spark 3.0.0版,基于成本的模型仍然不可用,并且正在使用临时解决方案,该解决方案采用sparkplan返回的第一个计划:
回到我们的示例,优化逻辑计划中的逻辑运算符将转换为物理运算符。通过数据源策略将关系转换为文件扫描节点,该节点将过滤器谓词向下推到数据源,仅用于读取查询所需的数据。联接内部逻辑运算符已通过联接策略转换为SortMergeJoin (我们需要鼓励联接策略选择更有效的联接算法,例如广播)。
执行准备(Execution Preparation) Sparkplan将逻辑计划转换为物理计划后,需要执行准备规则列表以准备要执行的物理计划。
例如,ensurerequrement规则可确保满足物理运算符的所有要求 (如果否,则需要执行操作以满足要求)。在我们的示例中,为查询中的联接操作规划了SortMergeJoin运算符,SortMergeJoin运算符需要在执行之前进行reshuffle和排序,Ensurerequrement规则将添加一些必需的操作:
除了确保需求之外,准备规则还将确保计划子查询,正确使用数据分区和排序,如果应用,则重用交换和子查询。此外,在这个阶段插入了整个项目。
总结
本文简单介绍了Spark Catalyst的总体概况,给出了Spark SQL执行的流程图,粗略介绍了一条Spark SQL执行所经历的SQL解析、SQL分析、逻辑优化、物理计划、执行准备等过程,在后面的文章中将深入每个主题分析其中实现细节。
- THE END -
Spark SQL: Relational Data Processing in Spark论文地址:
https://people.csail.mit.edu/matei/papers/2015/sigmod_spark_sql.pdf