Spark SQL的基本架构与DataFrame概述

一、Spark SQL的基本概念

1,Spark SQL的组成

Spark SQL是Spark的一个结构化数据处理模块,提供一个DataFrame编程抽象,可以看做是一个分布式SQL查询引擎。
Spark SQL主要由Catalyst优化、Spark SQL内核、Hive支持三部分组成。
(1)Catalyst优化
处理查询语句的整个过程,包括解析、绑定、优化、物理计划等,主要由关系代数(relation algebra)、表达式(expression)以及查询优化(query optimization)组成。
(2)Spark SQL内核
处理数据的输入输出,从不同的数据源(结构化数据Parquet文件和JSON文件、Hive表、外部数据库、现有的RDD)获取数据,执行查询(execution of queries),并将查询结果输出成DataFrame。
(3)Hive支持
是指对Hive数据的处理,主要包括HiveQL、MetaStore、SerDes、UDFS等。

2,Spark SQL

Spark SQL的发展,和大数据的发展一样,经历了离线计算、准实时计算、实时计算三个阶段。
(1)离线计算阶段,在大数据发展初期,通过MapReduce模型编写程序直接进行数据查询,解决了海量数据处理问题,编程模型比较简单,可以和Java无缝对接,同时通过Streaming支持C++等多语言编程,产生了划时代的影响;随着数据量的增加和对实时性的要求,基于离线数据计算的输入输出受到磁盘I/O和网络速度的限制,效率成为离散计算的瓶颈。
(2)准实时计算阶段,为了提升编程和查询效率,发展了Hive数据仓库。Hive数据仓库基于HDFS存储构建,并允许使用类似于SQL的语法HiveQL进行数据查询,简化了MapReduce编程,在一定程度上提升了效率,但是并没有彻底解决效率问题。Hive的局限性,促进了Shark的产生。为了进一步提升效率,伯克利实验室使用Shark对Hive进行了改造,替换了Hive的物理引擎,速度得到提升。Shark是Spark生态环境的组件之一,它修改了内存管理、物理计划、执行三个模块,并使之能运行在Spark引擎上,使SQL查询的速度得到10~100倍的提升。然而不容忽视的是,Shark集成了大量的Hive代码,给优化和维护带来了很多麻烦。Shark对于Hive的太多依赖(如采用Hive的语法解析器、查询优化器等)制约了Spark各个组件的相互集成。随着性能优化和分析整合的进一步加深,基于MapReduce设计的部分无疑成为实时计算的瓶颈。
(3)实时计算阶段,为了更好地发展,给用户提供更好的体验,Spark SQL抛弃原有Shark的代码,汲取了Shark的优点,重新进行了开发;Spark SQL直接基于Spark架构进行实现,效率比Shark有所提升。Spark SQL作为新的SQL引擎,基于Catalyst的优化引擎可以直接对Spark内核进行优化处理。Spark SQL整合各种数据源,包括Parquet、JSON、NoSQL数据库和传统关系型数据库,程序在内存中的运行速度是Hadoop MapReduce程序在磁盘上运行速度的100倍。

3,Spark SQL架构

Spark SQL对SQL语句的处理和关系型数据库SQL处理类似,将SQL语句解析成一棵树(tree),然后通过规则(rule)的模式匹配,对树进行绑定、优化等,得到查询结果。
Tree的具体操作是通过TreeNode实现的;Rule是一个抽象类,是通过RuleExecutor完成的,应用于Spark SQL的Analyzer、Optimizer、Spark Planner等组件中,可以简便、模块化地对Tree进行Transform操作。
在整个SQL语句处理过程中,Spark SQL主要依赖了Catalyst这个新的查询优化框架,把SQL解析成逻辑计划之后,Tree和Rule相互配合,利用Catalyst包里的一些类和接口,完成了解析(Analysis)、绑定、优化等过程,最终生成可以执行的物理计划,最后变成DataFrame的计算。

Spark SQL的执行过程:
Spark SQL的基本架构与DataFrame概述_第1张图片
其中树节点(TreeNodes)是指Scala Case类的变换树(transforming trees);SQL解析器(SQL parser)完成SQL语句的语法解析功能,将SQL语句解析成一棵Unresolved逻辑计划树;规则(rules)针对树进行分析、优化。
在Spark SQL的运行架构中,逻辑计划(logical plan)贯穿了大部分过程,其中,Catalyst的SqlParser、Analyzer、Optimizer都要对逻辑计划进行操作;最终形成可执行的物理计划(physical plan)。
sqlContext是使用sqlContext.sql(sqlText)提交用户的查询语句,调用DataFrame(this,parseSql(sqlText))对SQL语句进行处理,执行流程如下:
(1)使用SqlParser对SQL语句进行解析,生成Unresolved逻辑计划(没有提取Schema信息);
(2)使用Catalyst分析器,结合数据字典(catalog)进行绑定,生成Analyzed逻辑计划,在此过程中,Schema Catalog则要提取Schema信息;
(3)使用Catalyst优化器对Analyzed逻辑计划进行优化,按照优化规则得到Optimized逻辑计划。
(4)接下来需要和Spark Planner进行交互,使用策略(strategy)到plan,使用Spark Planner将逻辑计划转换成物理计划,然后调取next函数,生成可执行物理计划。
(5)调用toDF,最后生成DataFrame。

4,Spark SQL特点

(1)数据兼容方面:不但兼容Hive,还可以从RDD、Parquet文件、JSON文件中获取数据。可以在Scala代码里访问Hive元数据,执行Hive语句,并且把结果取回作为RDD使用。支持Parquet文件的读写,且保留Schema。
(2)组件扩展方面:无论是SQL的语法解析器、分析器,还是优化器都可以重新定义,进行扩展。
(3)性能优化方面:除了采取内存列存储、动态字节码生成等优化技术,还采取了内存缓存数据。
(4)支持多种语言:包括Scala、Java、Python、R等,可以在Scala代码里写SQL,支持简单的SQL语法检查,能把RDD转化为DataFrame存储起来。

5,Spark SQL性能

Spark SQL兼容了Hive的大部分语法和UDF,在处理查询计划时,使用了Catalyst框架进行优化,优化成适合Spark编程模型的执行计划,其效率比Hive高出很多。
(1)内存列式存储。
Spark SQL使用内存列式模式(in-memory columnar format)缓存表,仅扫描需要的列,并且自动调整压缩比使内存使用率和GC压力最小化,如果缓存了数据,则再次执行时不需要重复读取数据。
(2)动态代码生成和字节码生成技术,提升了复杂表达式求值查询的速率。
如下查询:
SELECT a + b FROM table
在这个查询语句中,传统的处理方式,会生成一个表达式树,需要调用虚函数确认Add两边的数据类型,然后分别调用虚函数确认a和b的数据类型,并装箱,最后调用指定数据类型的Add,返回装箱后的计算结果。计算时多次涉及虚函数的调用,虚函数的调用会打断CPU的正常流水线处理,减缓执行速度。
Spark SQL的基本架构与DataFrame概述_第2张图片
作为Spark SQL优化的一部分,已经实现了新的表达式计算,增加了codegen模块,Spark SQL在执行物理计划时,会对匹配的表达式采用特定的代码动态编译,能够为每个查询动态生成自定义字节码,然后运行。
内存列式存储和动态代码生成仅仅是冰山一角

你可能感兴趣的:(大数据,Hadoop,Spark,spark,sql,架构)