一.Hive on Spark的定义
Hive on Spark是由Cloudera发起,由Intel、MapR等公司共同参与的开源项目,其目的是把Spark作为Hive的一个计算引擎,将Hive的查询作为Spark的任务提交到Spark集群上进行计算。通过该项目,可以提高Hive查询的性能,同时为已经部署了Hive或者Spark的用户提供了更加灵活的选择,从而进一步提高Hive和Spark的普及率。
二.把Spark作为新的计算引擎供给Hive使用。
在Hive中, 一条SQL语句从用户提交到计算并返回结果,大致流程如下图所示(Hive 0.14中引入了基于开销的优化器(Cost BasedOptimizer,CBO),优化的流程会略有不同。
语法分析阶段,Hive利用Antlr将用户提交的SQL语句解析成一棵抽象语法树(Abstract Syntax Tree,AST)。
生成逻辑计划包括通过Metastore获取相关的元数据,以及对AST进行语义分析。得到的逻辑计划为一棵由Hive操作符组成的树,Hive操作符即Hive对表数据的处理逻辑,比如对表进行扫描的TableScanOperator,对表做Group的GroupByOperator等。
逻辑优化即对Operator Tree进行优化,与之后的物理优化的区别主要有两点:一是在操作符级别进行调整;二是这些优化不针对特定的计算引擎。比如谓词下推(Predicate Pushdown)就是一个逻辑优化:尽早的对底层数据进行过滤以减少后续需要处理的数据量,这对于不同的计算引擎都是有优化效果的。
生成物理计划即针对不同的引擎,将Operator Tree划分为若干个Task,并按照依赖关系生成一棵Task的树(在生成物理计划之前,各计算引擎还可以针对自身需求,对Operator Tree再进行一轮逻辑优化)。比如,对于MapReduce,一个GROUP BY+ORDER BY的查询会被转化成两个MapReduce的Task,第一个进行Group,第二个进行排序。
物理优化则是各计算引擎根据自身的特点,对Task Tree进行优化。比如对于MapReduce,Runtime Skew Join的优化就是在原始的Join Task之后加入一个Conditional Task来处理可能出现倾斜的数据。
最后按照依赖关系,依次执行Task Tree中的各个Task,并将结果返回给用户。每个Task按照不同的实现,会把任务提交到不同的计算引擎上执行。
三.Hive on Spark总体的设计思路
尽可能重用Hive逻辑层面的功能;从生成物理计划开始,提供一整套针对Spark的实现,比如SparkCompiler、SparkTask等,这样Hive的查询就可以作为Spark的任务来执行了。以下是几点主要的设计原则。
尽可能减少对Hive原有代码的修改。这是和之前的Shark设计思路最大的不同。Shark对Hive的改动太大以至于无法被Hive社区接受,Hive on Spark尽可能少改动Hive的代码,从而不影响Hive目前对MapReduce和Tez的支持。同时,Hive on Spark保证对现有的MapReduce和Tez模式在功能和性能方面不会有任何影响。
对于选择Spark的用户,应使其能够自动的获取Hive现有的和未来新增的功能。
尽可能降低维护成本,保持对Spark依赖的松耦合。
四.新的计算引擎
Hive的用户可以通过hive.execution.engine来设置计算引擎,目前该参数可选的值为mr和tez。为了实现Hive onSpark,我们将spark作为该参数的第三个选项。要开启Hive on Spark模式,用户仅需将这个参数设置为spark即可。
以Hive的表作为RDD。Spark以分布式可靠数据集(Resilient Distributed Dataset,RDD)作为其数据抽象,因此我们需要将Hive的表转化为RDD以便Spark处理。本质上,Hive的表和Spark的HadoopRDD都是HDFS上的一组文件,通过InputFormat和RecordReader读取其中的数据,因此这个转化是自然而然的。
使用Hive原语
这里主要是指使用Hive的操作符对数据进行处理。Spark为RDD提供了一系列的转换(Transformation),其中有些转换也是面向SQL的,如groupByKey、join等。但如果使用这些转换(就如Shark所做的那样),就意味着我们要重新实现一些Hive已有的功能;而且当Hive增加新的功能时,我们需要相应地修改Hive on Spark模式。有鉴于此,我们选择将Hive的操作符包装为Function,然后应用到RDD上。这样,我们只需要依赖较少的几种RDD的转换,而主要的计算逻辑仍由Hive提供。
由于使用了Hive的原语,因此我们需要显式地调用一些Transformation来实现Shuffle的功能。下表中列举了Hive onSpark使用的所有转换。
五.当执行SparkSQL语句的顺序
1.读入的SQL语句进行解析(Parse),分辨出SQL语句中哪些词是关键词(如SELECT、FROM、WHERE),哪些是表达式、哪些是Projection、哪些是Data Source等,从而判断SQL语句是否规范;
Projection:简单说就是select选择的列的集合,参考:SQL Projection
2.将SQL语句和数据库的数据字典(列、表、视图等等)进行绑定(Bind),如果相关的Projection、Data Source等都是存在的话,就表示这个SQL语句是可以执行的;
3.一般的数据库会提供几个执行计划,这些计划一般都有运行统计数据,数据库会在这些计划中选择一个最优计划(Optimize);
4.计划执行(Execute),按Operation–>Data Source–>Result的次序来进行的,在执行过程有时候甚至不需要读取物理表就可以返回结果,比如重新运行刚运行过的SQL语句,可能直接从数据库的缓冲池中获取返回结果。
Hive on Spark与SparkSql的区别
hive on spark大体与SparkSQL结构类似,只是SQL引擎不同,但是计算引擎都是spark!敲黑板!这才是重点!
Hive on Mapreduce和SparkSQL使用场景
Hive on Mapreduce场景
Hive的出现可以让那些精通SQL技能、但是不熟悉MapReduce 、编程能力较弱与不擅长Java语言的用户能够在HDFS大规模数据集上很方便地利用SQL 语言查询、汇总、分析数据,毕竟精通SQL语言的人要比精通Java语言的多得多
Hive适合处理离线非实时数据。
SparkSQL场景
Spark既可以运行本地local模式,也可以以Standalone、cluster等多种模式运行在Yarn、Mesos上,还可以运行在云端例如EC2。此外,Spark的数据来源非常广泛,可以处理来自HDFS、HBase、 Hive、Cassandra、Tachyon上的各种类型的数据。
实时性要求或者速度要求较高的场所
sparksql和hive on spark时间差不多,但都比hive on mapreduce快很多,官方数据认为spark会被传统mapreduce快10-100倍。
在Hadoop的整个生态系统中,Spark和MapReduce在同一个层级,即主要解决分布式计算框架的问题。
都支持ThriftServer服务,为JDBC提供解决方案,区别如下:
Spark SQL
=> 是Spark的一个库文件;
=> Spark SQL 元数据可有可无;
=> Spark SQL 中 schema 是自动推断的;
=> 支持标准 SQL 语句,也支持 HQL 语句等(可以用普通话、方言来对比理解);
=> 从开发角度来讲,即支持SQL方式开发,也支持HQL开发,还支持函数式编程(DSL)实现SQL语句。
Hive
=> 是一个框架;
=> Hive中必须有元数据,一般由 MySql 管理,必须开启 metastore 服务;
=> Hive 中在建表时必须明确使用 DDL 声明 schema;
=> 只支持 HQL 语句。
Hive:处理海量数据,比如一个月、一个季度、一年的数据量,依然可以处理,虽然很慢;
Spark SQL:这种情况下 Spark SQL 不支持,无法处理;
所以在企业中,Hive 和 Spark SQL 能够共存,互为弥补。
- 作用
(1)速度快:相对于hadoop来说,spark基于内存的运算效率要快100倍以上,基于硬盘的运算效率也要快个10倍以上。Spark实现了高效的DAG执行引擎,能够通过内存计算高效地处理数据流。
(2)易通用:spark支持多种编程语言(java、python、scala、R),超过80种高级算法,支持交互式的shell操作。
(3)通用性:适用场景广泛,大数据分析统计,批处理,交互式查询(spark sql),实时流数据处理(spark streaming),图计算(graphX)及机器学习(spark mllib),可以相互结合使用。
(4)容错性高: Spark引进了弹性分布式数据集RDD (Resilient Distributed Dataset) 的抽象,它是分布在一组节点中的只读对象集合,这些集合是弹性的,如果数据集一部分丢失,则可以根据“血统”(即充许基于数据衍生过程)对它们进行重建。 - 使用场景
(1)复杂的批量处理(Batch Data Processing),偏重点在于处理海量数据的能力,至于处理速度可忍受,通常的时间可能是在数十分钟到数小时
(2)基于历史数据的交互式查询(Interactive Query),通常的时间在数十秒到数十分钟之间。
(3)基于实时数据流的数据处理(Streaming
Data Processing),通常在数百毫秒到数秒之间 - 架构与生态
如果我们处理的数据量超过了单机所能够承受的范围(一般单机的运行内存为4GB、8GB、12GB等),我们可以选择spark集群进行计算。但有时我们处理的数据量不大,但是计过程很复杂,也可以使用spark集群处理。
(1)Spark的整体架构如下: - Spark Core:spark核心组件,实现的基本功能有任务调度、内存管理、错误恢复、与存储系统交互等模块。以及对弹性分布式数据集(RDD)的定义,RDD只读的分区记录的集合,只能基于在稳定物理存储中的数据集和其他已有的RDD上执行确定性操作来创建。
Spark sql: 提供通过Apache
Hive的SQL变体Hive查询语言(HiveQL)与Spark进行交互的API。用来操作结构化数据的核心组件。使用Spark sql可以查询hive、hbase等多种外部数据源中的数据。可以统一处理关系表和RDD。每个数据库表被当做一个RDD,Spark SQL查询被转换为Spark操作。
Spark Streaming:spark 提供流式计算框架,支持高吞吐量、可容错处理的实时流式数据处理,核心原理是将流数据分解成一系列短小的批处理作业,每个短小的批处理作业都可以使用spark core 进行快速处理。并支持多种数据源(kafka、flume以及TCP套接字等)
MLlib:一个常用机器学习算法库,算法被实现为对RDD的Spark操作。
GraphX:控制图、并行图操作和计算的一组算法和工具的集合。
独立调度器、yarn、mesos:这些都成为集群管理器。主要负责各个节点的资源管理工作,为了实现高效地在一个到数千个节点之间的伸缩计算,spark支持在各种集群管理器上运行。
(2)Spark的架构设计:
Hadoop存在很大的缺陷,其基于磁盘,无论是MapReduce还是YARN都是将数据从磁盘中加载出来,经过DAG,然后重新写回到磁盘中,计算过程的中间数据又需要写入到HDFS的临时文件,这些都使得Hadoop在大数据运算上表现太“慢”,Spark应运而生。
注DAG:Tez中Hortonworks开发的DAG计算框架,是从MapReduce计算框架演
化而来的通用DAG计算框架,核心思想是将Map和Reduce两个操作进一步拆分,即Map被拆分成Input、Processor、Sort、 Merge和Output, Reduce被拆分成Input、Shuffle、Sort、Merge、Processor和Output等,这样,这些分解后的元操作可以任意灵活组
合,产生新的操作,这些操作经过一些控制程序组装后,可形成一个大的DAG作业,可以用来替换Hive/Pig等。
Spark: RDD实现了以操作本地集合的方式来操作分布式数据集的抽象实现.。RDD是Spark最核心的东西,它表示已被分区,不可变的并能够被并行操作的数据集合,不同的数据集格式对应不同的RDD实现。RDD必须是可序列化的。RDD可以cache到内存中,每次
对RDD数据集的操作之后的结果,都可以存放到内存中,下一个操作可以直接从内存中输入,省去了MapReduce大量的磁盘IO操作。
元数据的结构是DAG(有向无环图),其中每一个“顶点”是RDD(包括生产该RDD的算子),从父RDD到子RDD有“边”,表示RDD间的依赖性。Spark给元数据DAG取了个很酷的名字,Lineage(世系).
(3)Spark的运行架构:
1)Application(应用):spark上运行的应用。包含了一个驱动器(driver)进程和集群上的多个执行器(executor)进程。
2)DriverProgram(驱动器):运行main方法并创建sparkcontext的进程。3)ClusterManager(集群管理器):用于在集群上申请资源的外部服务(独立部署的集群管理器、mosos或者yarn)
4)workerNode(工作节点):集群上运行应用程序代码的任意一个节点。
5)Executor(执行器):在集群工作节点上为某一个应用启动的工作进程,该进程负责运行计算运行任务,并为应用程序存储数据。
6)task(任务):执行器的工作单元
7)job(作业):一个并行计算作业,由一组任务组成,并由spark的行动算子触发启动。
8)stage(阶段):每个job可以划分为更小的task集合,每组任务被称为stage。
Spark应用在集群上运行时,Sparkcontext对象协调多个进程,与集群管理器通信,连接上就为该应用申请执行器,用于执行计算任务和存储数据。Sparkcontext对象将分割出的任务发送给各个执行器去执行。驱动器程序在整个生命周期内必须监听并接受其对应的各个执行器的连接请求,必须被所有的worker节点访问到。
WorkerNode是可以干活的节点,听大管家ClusterManager差遣,是真正有资源干活的主。从节点,负责控制计算节点,启动Executor或者Driver。
Executor是在WorkerNode上起的一个进程,相当于一个包工头,负责准备Task环境和执行
Task,负责内存和磁盘的使用。Task是施工项目里的每一个具体的任务。
Driver是统管Task的产生与发送给Executor的,运行Application的main()函数,是甲方的司令员。
SparkContext是与ClusterManager打交道的,负责给钱申请资源的,是甲方的接口人。
(4)spark运行基本流程图
1.构建Spark Application的运行环境,启动SparkContext
2.SparkContext向资源管理器(可以是Standalone,Mesos,Yarn)申请运行Executor资源,并启动StandaloneExecutorbackend,
3.Executor向SparkContext申请Task
4.SparkContext将应用程序分发给Executor
5.SparkContext构建成DAG图,将DAG图分解成Stage、将Taskset发送给Task
Scheduler,最后由Task Scheduler将Task发送给Executor运行
6.Task在Executor上运行,运行完释放所有资
- Spark和hadoop的对比、
(1)编程方式:hadoop的mapreduce的计算数据时,计算过程必须要转化为map和reduce。而spark的计算模型不局限于map和reduce操作,还提供多种数据集的操作类型,编程模型比mapreduce更加灵活
(2)数据存储:mapreduce计算结果都是存储在本地磁盘中,而spark计算产生的结果存储在内存中。
(3)数据处理:hadoop每次执行数据处理时,都需要从磁盘中加载数据,导致磁盘的I/O开销较大;而spark在执行数据处理时,只需要将数据加载到内存中,之后直接在内存中加载中间结果数据集即可,减少磁盘I/O开销。Mapreduce相对来说,计算延迟较高,无法更好的实现实时、快速计算的需求。
(4)数据容错:hadoop的计算引擎处理结果保存在磁盘中且底层架构实现了备份机制,从而保证了数据容错;同样spark RDD实现了基于lineage的容错机制和设置检查点的容错机制,弥补了内存处理时断电丢失的问题。 - Spark和hadoop的执行流程
(1)mapreduce的执行流程 - (2)spark的执行流程
- Hive on spark的原理:
1.Spark 以分布式可靠数据集(Resilient Distributed Dataset,RDD)作为其数据抽象,因此我们需要将Hive的表转化为RDD以便Spark处理
2.Spark为RDD提供了一系列的转换(Transformation), 但如果使用这些转换(就如Shark所做的那样),就意味着我们要重新实现一些Hive已有的功能;而且当 Hive增加新的功能时,我们需要相应地修改Hive on Spark模式.。我们选择将Hive的操作符包装为Function,然后应用到RDD上。这样,我们只需要依赖较少的几种RDD的转换,而主 要的计算逻辑仍由Hive提供。