SparkSQL的基本认识
Spark SQL是用于结构化数据处理的Spark模块(结构化数据可以来自外部结构化数据源也可以通过RDD获取)。与基本的Spark RDD API不同,Spark SQL提供的接口为Spark提供了有关数据结构和正在执行的计算的更多信息。在内部,Spark SQL使用此额外信息来执行额外的优化。有几种与Spark SQL交互的方法,包括SQL和Dataset API。在计算结果时,使用相同的执行引擎,与您用于表达计算的API /语言无关。这种统一意味着开发人员可以轻松地在不同的API之间来回切换,从而提供表达给定转换的最自然的方式。
下图为SparkSQL的基本架构:
这里我先给出一个SparkSQL的基本架构图。后面的内容我们会对其中的一些专有名词进行详细讲解,娓娓道来其中的内核。
SparkSQL的特点
- 支持多种数据源:Hive、RDD、Parquet、JSON、JDBC等。
- 多种性能优化技术:in-memory columnar storage、byte-code generation、cost model动态评估等。
- 组件扩展性:对于SQL的语法解析器、分析器以及优化器,用户都可以自己重新开发,并且动态扩展。
Spark SQL的性能优化技术简介
1、内存列存储(in-memory columnar storage)
内存列存储意味着,Spark SQL的数据,不是使用Java对象的方式来进行存储,而是使用面向列的内存存储的方式来进行存储。也就是说,每一列,作为一个数据存储的单位。从而大大优化了内存使用的效率。采用了内存列存储之后,减少了对内存的消耗,也就避免了gc大量数据的性能开销。
2、字节码生成技术(byte-code generation)
Spark SQL在其catalyst模块的expressions中增加了codegen模块,对于SQL语句中的计算表达式,比如select num + num from t这种的sql,就可以使用动态字节码生成技术来优化其性能。
3、Scala代码编写的优化
对于Scala代码编写中,可能会造成较大性能开销的地方,自己重写,使用更加复杂的方式,来获取更好的性能。比如Option样例类、for循环、map/filter/foreach等高阶函数,以及不可变对象,都改成了用null、while循环等来实现,并且重用可变的对象。
Spark SQL主要用于进行结构化数据的处理。它提供的最核心的编程抽象,就是DataFrame和DataSet。同时Spark SQL还可以作为分布式的SQL查询引擎。
DataSet和DataFrame
DataSet(数据集)是分布式数据集合[A Dataset is a distributed collection of data]。数据集是Spark 1.6中添加的一个新接口,它提供了RDD的优势(强类型,使用强大的lambda函数的能力)以及Spark SQL优化执行引擎的优点。数据集可以从JVM对象中被构造,然后使用transformation(转换操作)(map,flatMap,filter等等)。数据集API在Scala和 Java中可用。Python没有对Dataset API的支持。但由于Python的动态特性,数据集API的许多好处已经可用(即您可以自然地按名称访问行的字段 row.columnName)。R语言的情况类似。这里,博客中的实现代码大多采用Spark的原生代码scala实现。
DataFrame是组织为命名列的数据集[A DataFrame is a Dataset organized into named columns]。它在概念上等同于关系数据库中的表或R / Python中的数据框,但在引擎盖下具有更丰富的优化。DataFrame可以从多种来源构建,例如:结构化数据文件,Hive中的表,外部数据库或现有RDD。DataFrame API在Scala,Java,Python和R中可用。在Scala和Java中,DataFrame由Rows 的数据集表示。在Scala API中,DataFrame它只是一个类型别名Dataset[Row]。而在Java API中,用户需要使用Dataset来表示DataFrame。
在Spark的官网说明,我们经常将Row