Spark大数据商业实战三部曲:内核解密|商业案例|性能调优
上QQ阅读APP看书,第一时间看更新

2.3 Spark 2.2 SQL

Spark 2.0通过对SQL 2003的支持增强了SQL功能,Catalyst新引擎提升了Spark查询优化的速度;本节对DataFrame和Dataset API、时间窗口进行了讲解。

Apache Spark 2.2.0版本中核心和Spark SQL的更新如下。

1.API更新

 SPARK-19107:支持使用DataFrameWriter和Catalog创建hive表。

 SPARK-13721:增加支持LATERAL VIEW OUTER explode()。

 SPARK-18885:统一数据源和hive serde表的CREATE TABLE语法。

 SPARK-16475:增加广播提示BROADCAST、BROADCASTJOIN和MAPJOIN,用于SQL查询。

 SPARK-18350:支持会话本地时区。

 SPARK-19261:支持ALTER TABLE table_name和COLUMNS。

 SPARK-20420:将事件增加到外部目录。

 SPARK-18127:向Spark增加钩子和扩展点。

 SPARK-20576:在Dataset/DataFrame中支持通用提示功能。

 SPARK-17203:数据源选项应始终不区分大小写。

 SPARK-19139:基于AES的Spark认证机制。

2.性能优化和系统稳定性

基于成本的优化:

 SPARK-17075 SPARK-17076 SPARK-19020 SPARK-17077 SPARK-19350:过滤filter,关联join,聚合aggregate,投影project和限制limit/样本运算符sample的基数估计。

 SPARK-17080:基于成本的关联重新排序。

 SPARK-17626:使用星形模式启发的TPC-DS性能提升。

 SPARK-17949:引入基于JVM对象的聚合运算符。

 SPARK-18186:HiveUDAFFunction的部分聚合支持。

 SPARK-18362 SPARK-19918:CSV和JSON的文件列表/I/O改进。

 SPARK-18775:限制每个文件写入的最大记录数。

 SPARK-18761:不可取消/不能被杀掉的任务不应该资源短缺。

 SPARK-15352:拓扑识别块复制。

3.其他变化

 SPARK-18352:支持解析多行JSON文件。

 SPARK-19610:支持解析多行CSV文件。

 SPARK-21079:分析分区表上的表命令。

 SPARK-18703:对Hive-serde表插入/CTAS完成后,删除暂存目录和数据文件。

 SPARK-18209:更强大的视图规范化,无须完全SQL扩展。

 SPARK-13446:[SPARK-18112]支持从Hive metastore 2.0/2.1读取数据。

 SPARK-18191:使用提交协议的RDD API端口。

 SPARK-8425:增加黑名单机制进行任务调度。

 SPARK-19464:删除对Hadoop 2.5及更早版本的支持。

 SPARK-19493:删除Java 7支持。

2.3.1 Spark SQL

Spark 2.0通过对SQL 2003的支持大幅增强了SQL功能,现在可以运行所有99个TPC-DS查询。这个版本中的SparkSQL主要有以下几点改进:

(1)引入了支持ANSISQL和HiveSQL的本地解析器。

(2)本地实现DDL命令。

(3)支持非相关标量子查询。

(4)在Where与having条件中,支持(not)in和(not)exists。

(5)即使Spark没有和Hive集成搭建,SparkSQL也支持它们一起搭建时的除了Hive连接、Hive UDF(User Defined Function用户自定义函数)和脚本转换之外的大部分功能。

(6)Hive式的分桶方式的支持。

另外,Catalyst查询优化器对于常见的工作负载也有了很多提升,对如nullability propagation之类的查询做了更好的优化。Catalyst查询优化器从最早的应用于SparkSQL到现在应用于DataSetAPI,对Spark程序的高效率运行起到了非常重要的作用,并且随着DataSetAPI的流行,以及优化器自身的不断演进,未来肯定会对Spark的所有框架带来更高的执行效率。

2.3.2 DataFrame和Dataset API

在Spark 1.X版本中,DataFrame的API存在很多问题,如DataFrame不是类型安全的(not type-safe)、不是面向对象的(not object-oriented),为了克服这些问题,Spark在1.6版本引入了Dataset,并在2.0版本的Scala和Java中将二者进行了统一(在Python和R中,由于缺少类型安全性,DataFrame仍是主要的编程接口),DataFrame成为DataSet[Row]的别名,而且Spark 2.0版本为DataSet的类型化聚合加入了一个新的聚合器,让基于DataSet的聚合更加高效。

在Spark 2.1版本中,DataFrame和Dataset API晋升为稳定的API。也就是说,可以在生产实践中使用它们,且后续会基于向后兼容的前提不断强化。

DataSetAPI是High-LevelAPI,有更高的抽象级别,与RDDAPI这样的Low-LevelAPI相比更加易用,它对于提升用户的工作效率,以及提高程序的可读性而言意义非凡。由于WholeStageCodeGeneration的引入,SparkSQL和DataSetAPI中的常见算子的性能提升了2~10倍。加上Catalyst查询优化器和Tungsten的帮助,用户不用过多地关注对程序的优化,也能获得很好的执行效率。

所以,毋庸置疑地,这样一种简单高效的API将成为Spark未来主流的编程接口。

2.3.3 Timed Window

对于经常用到复杂SQL的用户而言,窗口函数一直以来都是不可或缺的,在Spark 2.X版本中,通过对Hive中的窗口函数的本地化实现,使用Spark的内存管理机制,从而提升了窗口函数的性能。