目标
- 在CDH集群的查询client中(包括webUI如HUE)使用Spark作为Hive-SQL的执行引擎。
- 调研版本、使用方法、性能与适用范围、是否有语法差异、对parquet/orc等的支持、调优、稳定性、对集群压力等问题。
- 基于调研结果深入背后的原理,理解现象的原因
资料
官方文档CDH5.13.x
官方文档CDH5.13.x相关配置
Hive on Spark解析
Hive使用Spark on Yarn作为执行引擎
Hive,Hive on Spark和SparkSQL区别
Hive on spark的架构与解析SQL的过程
Spark SQL你不得不知道的那些事儿
Hive on Spark与Spark SQL
-
MR是基于进程并行处理的,hive里面很多代码并没有注意线程安全问题,但spark基于线程,导致Shark得用一套单独维护打了补丁的hive的分支,没有办法合并到hive。之后停止维护,形成了两套方案,一个是从头开始的Spark SQL,一个是Hive on Spark。
- Hive执行引擎(Execution Backend)有MR、Tez,以及后来的Spark,即将Hive的Compiler生成的执行计划提交给Spark集群上运行,这是Hive的功能。
tez和spark都是通用有向无环图DAG引擎,他们比MapReduce更加灵活,性能也更优越,比如,在使用MapReduce时,中间作业的输出会被物化储存到hdfs上,tez和spark则不同,他们可以根据hive规划器的请求,把中间结果写在本地磁盘,甚至是内存中缓存,以避免额外的复制开销
-
在Spark程序中通过hiveContext.sql()查询Hive是Spark SQL的特性,让Spark SQL除了从TextFile中读取数据外还能直接读取Hive表。SparkSQL主要包括两个概念:
- SQLContext:封装Spark中的所有关系型功能。
- DataFrame:可转换为RDD进行操作。
-
小结
Hive / SparkSQL做的是解析SQL,是翻译层;Spark/MapReduce在执行引擎层。所以SparkSQL存在部分语法与Hive不兼容:https://blog.csdn.net/zhoudetiankong/article/details/50295709
讨论的两者对应的就是Hive->Spark与SparkSQL->Spark。前者只需要编写SQL,后者可以结合spark写代码获得更灵活的操作.
基于Spark的Hive能提供Hive的所有功能,因为它本身隶属于Hive项目。
SQL只是Spark SQL的一个功能而已,利用Dataframe来结合rdd操作会更加强大。
实验
- 集群环境
- Hadoop版本:2.6.0-cdh5.13.1(hadoop version)
- Hive版本:1.1.0 (file /opt/cloudera/parcels/CDH-5.13.1-1.cdh5.13.1.p0.2/jars/hive-common-1.1.0-cdh5.13.1.jar)
- 集群位数:ELF 64-bit LSB shared object, x86-64, version 1 (SYSV)
(file /opt/cloudera/parcels/CDH/lib/hadoop/lib/native/libhadoop.so.1.0.0) - Spark版本:spark-1.6.0+cdh5.13.3+543(待验证。目前只是从官网上看到的https://www.cloudera.com/documentation/enterprise/release-notes/topics/cdh_vd_cdh_package_tarball_513.html)
2、安装相关配置
很多教程中会让在hive-site.xml中做相关配置,但CDH5.13环境下不会看到这些配置(理解为被写死了,版本也固定为1.6,官方说尚未适配高版本spark)
3、使用方法
set hive.execution.engine=spark;
set hive.execution.engine; //确认设置成功
简单配置后即可照常执行HiveSQL
性能与调优
- 开启新的Hive on Spark会话后首次查询缓慢
- 现象:新Hive on Spark会话启动后的首次查询可能延迟,在Spark on Yarn集群上
要启动时间。 - 原因:查询需要等待Yarn containers初始化
- 解决方法:无。接下来的查询会快。
大部分基于mr的调优设置在Spark下依然有效,这里说明一些特殊情况。
2、写入语句
对10000行某表进行create table 与insert overwrite操作,spark耗时20+秒,mr耗时30+秒
- 对在分区字段上的map join进行剪枝优化
SET hive.spark.dynamic.partition.pruning.map.join.only=true;
- 使用更多的executor
测试一个包含大量join的复杂语句,分别使用不同引擎与不同的如下设置
set spark.executor.instances=n; // 默认值n=2
mr | spark n=2 | spark n=4 | spark n=8 |
---|---|---|---|
6m10s | 5m18s | 2m52s | 2m26s |
基于目前集群资源情况,该值最高取32。
可以看到Spark在数据量大、join复杂情况下优势降低。并且该参数值有边际递减效应。
集群相关参数
目前分析师共用user队列,单个应用申请CPU与内存资源不宜超过队列资源的1/3。
目前符合官网推荐规则,不建议手动修改
- spark.driver.cores=1 //即am核数
- spark.driver.memory=3.6Gb
- yarn.nodemanager.resource.cpu-vcores=16
- spark.executor.cores=4
- yarn.nodemanager.resource.memory-mb=24Gb
- spark.executor.memory=4G
- spark.yarn.driver.memoryOverhead=409Mb
语法与功能
因为SQL解析引擎依然是Hive,语法与功能完全与Hive兼容,这里做了如下测试。
能够照常使用平台公共的临时UDF
create temporary function check_mobile as 'com.tal.hive.udf.CheckMobileNo';
select check_mobile('150');能够正常查询Parquet与Orc格式的表
insert overwrite与create table as等写入语句可以执行。
问题
目前版本的cdh/HUE/Hive存在一个bug:为了让用户不用每次等待Spark Session的启动(7.1中所述),Session会保留非常长的时间,即使HUE页面关闭。
为了保证资源及时释放,请务必在关闭客户端页面前、长时间不使用时将当前session的执行引擎切换回mr:
set hive.execution.engine=spark;
...//用户正常业务SQL
set hive.execution.engine=mr;// 务必注意`
相同现象问题与官方issue:https://stackoverflow.com/questions/46676323/spark-on-hive-progress-bar-stuck-at-10
大神Fayson的论述:https://cloud.tencent.com/developer/article/1176754