Spark SQL原理及实战

一、Spark SQL的发展

1、spark SQL和shark  

  SparkSQL的前身是Shark,给熟悉RDBMS但又不理解MapReduce的技术人员提供快速上手的工具,Hive应运而生,它是当时唯一运行在Hadoop上的SQL-on-Hadoop工具。但是MapReduce计算过程中大量的中间磁盘落地过程消耗了大量的I/O,降低的运行效率,为了提高SQL-on-Hadoop的效率,大量的SQL-on-Hadoop工具开始产生,其中表现较为突出的是:

    1、MapR的Drill

    2、Cloudera的Impala

    3、Shark

  Shark对于Hive的太多依赖(如采用Hive的语法解析器、查询优化器等等),但SparkSQL摆脱了对Hive的依赖性,无论在数据兼容、性能优化、组件扩展方面都得到了极大的方便。

    1、数据兼容方面  不但兼容Hive,还可以从RDD、parquet文件、JSON文件中获取数据,未来版本甚至支持获取RDBMS数据以及cassandra等NOSQL数据;

    2、性能优化方面  除了采取In-Memory Columnar Storage、byte-code generation等优化技术外、将会引进Cost Model对查询进行动态评估、获取最佳物理计划等等;

    3、组件扩展方面  无论是SQL的语法解析器、分析器还是优化器都可以重新定义,进行扩展;

2、Spark SQL的性能

  1)内存列存储(In-Memory Columnar Storage)

    

    对于内存列存储来说,将所有原生数据类型的列采用原生数组来存储,将Hive支持的复杂数据类型(如array、map等)先序列化后并接成一个字节数组来存储。这样,每个列创建一个JVM对象,从而导致可以快速地GC和紧凑的数据存储。额外的,还可以用低廉CPU开销的高效压缩方法来降低内存开销。更有趣的是,对于分析查询中频繁使用的聚合特定列,性能会得到很大的提高,原因就是这些列的数据放在一起,更容易读入内存进行计算。

  2)字节码生成技术(bytecode generation,即CG)

    在数据库查询中有个昂贵的操作就是查询语句中的表达式,主要是由JVM的内存模型引起的。如SELECT a+b FROM table,这个查询里如果采用通用的SQL语法途径去处理,会先生成一个表达树,会多次设计虚函数的调用,这会打断CPU的正常流水线处理,减缓执行速度。

    spark -1.1.0在catalyst模块的expressions增加了codegen模块,如果使用动态字节码生成技术,Spark SQL在执行物理计划时,会对匹配的表达式采用特定的代码动态编译,然后运行。

SQL查询的CG优化

 

 3、Scala代码的优化

  Spark SQL在使用Scala语言编写代码时,应尽量避免容易GC的低效代码。尽管增加了编写代码的难度,但对于用户来说,还是使用了统一的接口,让开发在使用上更加容易。

  

 Scala代码的优化

二、Spark SQL运行架构

  SparkSQL有两个分支,sqlContext和hiveContext,sqlContext现在只支持SQL语法解析器(SQL-92语法);hiveContext现在支持SQL语法解析器和hivesql语法解析器,默认为hiveSQL语法解析器,用户可以通过配置切换成SQL语法解析器,来运行hiveSQL不支持的语法

  1)sqlContext具体的执行过程如下:

    1、SQL | HQL语句经过SqlParse解析成UnresolvedLogicalPlan;

    2、使用analyzer结合数据数据字典(catalog)进行绑定,生成resolvedLogicalPlan;在这个过程中,Catalog提取出SchemRDD,并注册类似case class的对象,然后把表注册进内存中。

    3、Analyzed Logical Plan经过Catalyst Optimizer优化器优化处理后,生成Optimized Logical Plan,该过程完成以后,以下的部分在spark core中完成。

    4、Optimized Logical Plan的结果交给SparkPlanner,然后SparkPlanner处理后交个PhysicalPlan,经过该过程后生成Spark Plan

    5、使用SparkPlan将LogicalPlan转换成PhysicalPlan;

    6、使用prepareForExecution()将PhysicalPlan转换成可执行物理计划;

    7、使用execute()执行可执行物理计划;

    8、生成SchemaRDD。

  在整个运行过程中涉及到多个SparkSQL的组件,如SqlParse、analyzer、optimizer、SparkPlan等等

  2)hiveContext总的一个过程如下图所示:

    1、SQL语句经过HiveQl.parseSql解析成Unresolved LogicalPlan,在这个解析过程中对hiveql语句使用getAst()获取AST树,然后再进行解析;

    2、使用analyzer结合数据hive源数据Metastore(新的catalog)进行绑定,生成resolved LogicalPlan;

    3、使用optimizer对resolved LogicalPlan进行优化,生成optimized LogicalPlan,优化前使用了ExtractPythonUdfs(catalog.PreInsertionCasts(catalog.CreateTables(analyzed)))进行预处理;

    4、使用hivePlanner将LogicalPlan转换成PhysicalPlan;

    5、使用prepareForExecution()将PhysicalPlan转换成可执行物理计划;

    6、使用execute()执行可执行物理计划

    7、执行后,使用map(_.copy)将结果导入SchemaRDD

hiveContext执行过程

三、catalyst优化器

  SparkSQL1.1.0总体上由四个模块组成:core、catalyst、hive、hive-Thriftserver:

    1)core处理数据的输入输出,从不同的数据源获取数据(RDD、Parquet、json等),将查询结果输出成schemaRDD;

    2)catalyst处理查询语句的整个处理过程,包括解析、绑定、优化、物理计划等,说其是优化器,还不如说是查询引擎;

    3)hive对hive数据的处理

    4)hive-ThriftServer提供CLI(命令行界面)和JDBC/ODBC接口

  catalyst处于最核心的部分,其性能优劣将影响整体的性能。

  

  

  从上图看,catalyst主要的实现组件有:

    1)sqlParse,完成sql语句的语法解析功能,目前只提供了一个简单的sql解析器;

    2)Analyzer,主要完成绑定工作,将不同来源的Unresolved LogicalPlan和数据元数据(如hive metastore、Schema catalog)进行绑定,生成resolved LogicalPlan;

    3)optimizer对resolved LogicalPlan进行优化,生成optimized LogicalPlan;

    4)Planner将LogicalPlan转换成PhysicalPlan;

    5)CostModel,主要根据过去的性能统计数据,选择最佳的物理执行计划

 

转载http://www.cnblogs.com/shishanyuan/p/4723604.html?utm_source=tuicool

posted @ 2016-03-19 16:10  liurio  阅读(1982)  评论(0编辑  收藏  举报