Zen项目
Zen项目在一年前开始启动,目标就是让spark对python用户更加友好
类型提示
重要的一步就是加了一些类型提示,例如他能够在IDE或者notebook中自动补全代码,这样能够使开发效率提高,在最新发布的spark 3.1.1能够全部支持类型提示
spark pandas
spark3.2的一个新的特性目标就是结合Koalas项目到spark中,如果数据科学家使用pandas操作数据,以及在大数据量的情况下会遇到性能问题,但是当使用spark作为backend的时候,Koalas可以使用pandas API,这样切换到Koalas就会变得非常容易,因为代码是保持一致的,但是却在spark下运行。当Koalas结合到spark中以后,这些环境机会变得更简单,你只需要从spark倒入pandas,使用spark中的pandas。pandas中的图标和可视化工具都是可用的。
Zen项目在峰会的这个部分讨论:Project Zen: Making Data Science Easier in PySpark
性能提升
随着spark的发版,引擎的性能得到了提高,在这次峰会里,大量跟性能有关的主题被涉及到:
shuffled hash join(SHJ)
Shuffle Hash Join 在spark进行数据连接中是可用的。实际上,它已经被sort-merge join(SMJ)取代了,因为SMJ更加稳定,SHJ在数据倾斜的情况下会导致OOM。在一些特定的场景下,SHJ会比SMJ运行的更快,因为它避免了排序。
在spark 3.1中一些列的努力使SHJ甚至更好,以及用处更加大:
其他关于SHJ的性能改善,在峰会的以下部分:
Deep Dive into the New Features of Apache Spark 3.1
向量化
向量化是在同一时间并行运行处理多行的的加速处理技术。在目前的spark版本中,通过使用向量化的reader我们可以读取parquet和orc文件,除了这部分以外,在pyspark中的pandas UDFs中也支持使用到向量化.
实现向量化的一种方法是使用SIMD指令集(单指令,多数据),这个是在现在硬件中是支持的。目前的spark版本并不显示的使用SIMD的,因为JVM Hotspot编译器在一些场景会生成SIMD指令,有些不会。但是在java 16有了Vector API,这个API将会确保SIMD指令会用到。所以有了VectorAPI,在spark代码生成中显示的指定向量化是可以的。
向量化的在峰会的以下部分讨论:
Enabling Vectorized Engine in Apache Spark
Zstandard 压缩编码
Apache Spark支持各种各样的压缩算法,例如:当写入数据到parquets文件的时候,snappy是默认的算法, 另一方面,lz4用于shuffle 文件,其他的编码也是支持的。Ztandard实现了有snappy一样的压缩速度,和gzip一样的压缩率。
从spark 3.2以来,ZStandard 将会一下三个场景下带来性能提升(存储本地文件/存储到外部存储/总体查询执行加速):
- 事件日志压缩(spark.eventLog.compression.codec=zstd)
- shuffle中的io压缩(spark.io.compression.codec=zstd)
- parquet/orc文件压缩
spark.conf.set(“spark.sql.parquet.compression.codec”,“zstd”)
相关的峰会讨论如下:
The Rise of ZStandard: Apache Spark/Parquet/ORC/Avro
shuffle 增强
shuffle在spark中是最昂贵的处理了,因为它必须在节点之间进行数据的移动。shuffle是两个stage的边界,在一个stage结束后,结果被写入到文件,然后在下一个stage会被拉取。这些文件要么存储在executor的本地磁盘或者当外部存储开启时,他会被存储到外部文件系统,如hdfs。文件的数量跟着task数量成指数增长(具体的来说,是上游的task的数量乘以下游的task的数量),并且文件是比较小的。这里有一个jira用来实现所谓的基于push的shuffle,这将通过提前merge blocks来优化shuffle IO。关于这个技术相关的文章可以在这里查看
这部分的在峰会的一下部分讨论: Magnet Shuffle Service: Push-based Shuffle at LinkedIn
处理复杂查询计划
对于一些查询,查询计划可能变得很复杂,那么他的编译就会变为瓶颈,这里有个 jira 试着去简化处理拥有别名的列,并且测试结果显示是如期的加速了
这部分的峰会如下:Optimizing the Catalyst Optimizer for Complex Plans
ANSI SQL 编译
这是一个还在开发的项目,在spark 3.0 发布了一个实验性质的配置项,spark.sql.ansi.enabled ,当我们设置为true的时候,spark将会遵循ANSI SQL的标准,这意味者如果一个查询的输入是无效的话,该查询是会在运行的时候失败的,尽管它能返回null值,一个具体的例子就是数据类型的不安全得到cast的转化,或者是迷糊的转化,一些相关的的新函数将会在spark 3.2中发布,例如TRY_CAST,TRY_ADD,TRY_DIVIDE,这些函数是很有用过得,如果想用使用ANSI模式的话,除非在输入无效的情况下更倾向于null值而不是使查询失败。
在spark 3.2 两个新间隔时间类型将会被发布,year-month和day-time,这将会解决目前CalendarIntervalIntervalType存在的问题。这里有个正在处理的jira,这是一个相关子问题的大纲。目前interval 类型存在问题是,它是不可比较的,而且不支持排序,所以让两个intervals类型进行比较谁大谁小是行不通的。另一个问题是我们不能存储interval类型到parquet/orc设置json文件中。从另一方面讲,在spark 3.2发布的新的YearMonthIntervalType和DayTimeIntervalType类型将会是可对比的,可排序的,将会符合ANSI标准的。
更多的关于ANSI SQL编译的信息或者细节,可以参考文档。或者参考一下峰会部分:
- Deep Dive into the New Features of Apache Spark 3.1
- Comprehensive View on Intervals in Apache Spark 3.2
DataSourceV2 API
DataSourceV2 API已经开发了好几年了,目标就是解决V1 API相关的问题,例如DataFrameWriter的不同模式下的不一致行为,写入表中的无schema的校验,依赖于其他内部api如SQLContext,以及对新特性的不容易扩展。 V2 API在底层使用了类目去检查表是否存在,并且使用一致性的校验规则,这些规则独立于连接器的实现。这里有个正在开发的jira 目标就是在分发和排序中更好的控制连接器,这将会有更好的可控性,并且计划在spark 3.2发布。 V2 API和相关的分布和排序在峰会该部分讨论: Data Distribution and Ordering for Efficient Data Source V2
总结
在2021年的北美数据+AI峰会中,有很多的有意思的部分。在这简短的报告中,从spark内部和最佳实践中,我总结了记录了一些有意思的部分.这些笔记绝不是完整的,我主要是聚焦于已经发布的3.1.1和即将发布的3.2的新特性中。
本文翻译自Highlights from Data + AI Summit NA 2021