SparkSession
从Spark2开始,Spark-SQL引入了SparkSession这个核心类,它是处理DataSet等结构数据的入口。在2.0之前,使用的是spark-core里的SparkContext。从前面的例子里也可以看到,程序一上来就要先创建SparkSession对象:
- SparkSession spark = SparkSession.builder().appName("Simple Application").master("local").getOrCreate();
如果是在Spark-shell中,默认提供了它的一个对象叫spark。
spark-shell是给scala环境使用的一个命令行调试工具
SparkSession组合了2.0之前的几种上下文类,比如SQLContext和HiveContext,所以使用这些的地方原则上可以都用SparkSes来代替了。不过其他上下文类依然存在,就像RDD对于DataSet一样,它们依然功能完整操作细腻,比不过是Spark提供了新的API来封装、简化操作。
我们来看一下上面那条创建语句:最后的方法含义清晰,有就返回,没有就创建。master方法用来指明在集群环境下的master是谁。在Standalone 模式下传local或local[n],n是spark执行任务时的期望分片数。
RDD/Dataset/DataFrame
Resilient Distributed Datasets (RDD) 译成弹性分布式数据集,是Spark中的核心概念。前面说过这个概念现在被Dataset和DataFrame代替了,但它依然存在。由于它的一些"缺点",导致Spark提供了更高级的API,但是在它之上构建的。
它是一组对象组成的不可变的分布式集合,里面的数据会被分成多个逻辑片在不同的节点上面计算。
在遇到RDD的时候,现在我们通常会将其转化为Dataset和DataFrame,因为DataFrame更好用,它提供了和关系表一样的具名列,更重要的是计算性能也更好。
转化的方法也很简单,之前我们用到了:toDF()。
dataset和dataFrame的区别是,dataset的泛型类型是明确的,所以是类型安全的,编译的时候就能检查问题,风格也更接近面向对象。而dataframe的泛型类型是Row,里面有哪些列要主动探知。
因为它们的数据结构是同一个,所以优化方式是一致的:能够利用Catalyst 查询引擎,堆外存储机制等。
Spark程序是运行了JVM上的,所以会有垃圾回收的过程。Spark为了不对计算数据进行GC扫描,通过Unsafe类使用了非堆内存
Encoder
编码器是用来将Java对象转化为Spark的二进制格式的,我们前面的例子里也用了一些内置的编码器,非常方便但是不好看。
上面说了spark使用了堆外内存,所以会涉及大量的数据序列化。Spark提供的编码器有一个强大的地方是,不用反序列化就能访问属性。