本文整理自《Spark SQL内核剖析》第11章 Spark SQL开发与实践,文章的图片版权归作者和出版社所有,侵权的话请联系删除。
这本书系统的讲解了Spark SQL的架构原理及其实现方式,书中的内容逻辑严密,结构清晰明了,作者从简单的Spark SQL 语句入手,一步步的带着我们探索Spark SQL是如何实现的,这本书是帮助我们深入理解Spark SQL原理的不二选择,欢迎大家购买原书进行学习。另京东读书上有电子版,阅读体验很好,值得尝试。(利益无关,纯粹是自来水)
这本书出版于2018年,作者均来自腾讯,使用Spark2.1/2.2版本进行讲解,现在看来,内容仍不过时,就像作者在书中所说的那样:“尽管各式各样的计算模型、处理框架、平台系统层出不穷,令人眼花缭乱难以选择,但是万变不离其宗,底层所涉及的分布式技术、编译原理、数据库理论等基础知识都是通用的。”
推荐的话说完了,这篇文章主要介绍Spark SQL在腾讯的开发和优化,在大数据/分布式场景下,每个组件都可能成为瓶颈,我们可以通过这篇文章看到腾讯大数据团队通过各种方式来优化组件性能,提高Spark SQL的易用性。
1.简单概况
兼容性:
兼容大数据平台特有的SQL语法(包括Oracle数据库)、数据存储格式、分区格式、元数据格式等。
新框架:
Spark SQL业务的Yarn-Cluster运行模式、On Demand的History Server、元数据库代理、HiveUDF/UDAF函数自动加载等。
新功能:
数据自动分区、自定义Python UDF/UDAF函数、多维分析组合使用等。
性能优化:
预排序的Join实现方式、多维分析的Union策略、SortMergeJoin执行过程中的数据存储优化等。
2.业务运行支撑框架
2.1 Yarn-Cluster提交模式
2.2 On Demand的HistoryServer
2.3 元数据库代理
2.4 HiveUDF/UDAF函数自动加载
为了做到函数的实时更新对业务保持透明,SQL-Engine将UDF/UDAF函数从Hive从解耦出来,单独维护。
这样,在提交SQL任务时,Spark系统首先自动加载UDF/UDAF函数。在解析SQL时,会先查找加载的HiveUDF/UDAF函数,查找失败时再去查找Spark SQL中的内置函数。
加载逻辑的代码片段如下:
3.新功能开发案例
3.1 字符串拼接
在Oracle中可以使用 || 的方式实现字符串拼接,想要在Spark SQL中兼容这种语法
需要进行如下两个操作
在文法文件SqlBase.g4中添加相应的文法,这里称为tdwConcat,代码如下:
其次,就是修改AstBuilder类生成对应的逻辑算子节点,需要加入针对tdwConcat的逻辑,即重载实现visitTdwConcat方法,代码如下,直接得到UnresolvedFunction,将其对应到concat函数。
3.2 灵活的多维分析组合
开源社区的Spark SQL只支持多维分析函数grouping sets、cube、rollup的单独使用,不支持组合使用,且只能通过关键字with选取固定的列。
在腾讯大数据平台TDW涉及的业务中,对多维分析的使用比较灵活,无法直接迁移到Spark SQL中,例如下面的SQL语句就会直接抛出语法错误。
针对该需求,内部的Spark SQL系统中加入了对多维分析函数组合使用的支持,大大增加了多维分析的灵活度,满足不同OALP业务的需求。
为了支持多维分析的灵活使用,需要在SQL语法中支持。本书第4章中已经介绍过Spark SQL语法编译器。
增加语法支持需要修改SqlBase.g4文件中与聚合相关的文法,代码如下。
修改后的语法会被翻译为抽象的语法树,语法树再被解析为逻辑计划。所以,为了使多维分析的语法生效,还需要修改执行逻辑。
在AstBuilder中,聚合操作会被翻译成逻辑计划GroupingSets。GroupingSets的定义如下。
3.3 自定义Python UDF/UDAF函数