通过Thrift Server使用JDBC来运行Spark SQL

通过Thrift Server使用JDBC来运行Spark SQL

标签(空格分隔): thriftserver jdbc sparkSQL


更新记录

初始发布:2017-09-19
第一次更新:xxx

简介

Thrift JDBC/ODBC Server (简称 Spark Thrift Server 或者 STS)是Spark SQL的Apache Hive HiveServer2的端口,通过这个端口可以允许用户使用JDBC/ODBC端口协议来执行SQL查询。
通过使用STS,商业用户就可以用使用一些炫目的BI工具,比如Tableau来连接Spark进行基于大数据量的报表制作。

开启与关闭服务

STS是Spark的一个独立应用,可以通过 start-thriftserver.sh 开启, stop-thriftserver.sh来关闭。

启动命令
sh $SPARK_HOME/sbin/start-thriftserver.sh
当修改了配置的时候,需要使用这个命令重启一些服务。

一些启动参数

sh $SPARK_HOME/sbin/start-thriftserver.sh \
--hiveconf hive.server2.thrift.port=10000 \
--master MASTER_URL \  //master的URL,如spark://host:port, mesos://host:port, yarn, 或local
--queue queue_name \   //如果使用yarn模式,设置队列名字
--num-executors NUM \   //executor的数目
--conf spark.driver.memory=40g \    //driver内存的大小
--driver-cores NUM  \   //driver CPU数目,cluster模式才有这个参数
--executor-memory 6g \  //executor内存大小,如果开启动态分配,这个就不需要了
--conf spark.yarn.executor.memoryOverhead=2048 \    //overhead大小

一些tips

1.ResultSize问题

driver内存问题,在有些场景下,需要把结果集拉到driver端,默认的结果集大小为1G,如果超过了这个数字,则会报错,需要设置对应的参数,如

--conf spark.driver.maxResultSize=10G

2.driver与executor32G内存问题导致的截断(https://issues.apache.org/jira/browse/SPARK-10914)

影响版本:1.5.0, 1.5.1
修复版本:1.5.2, 1.6.0
在一次关联任务中发现,在hive中可以关联的SQL任务,在SparkSQL中结果为空,查询几条数据发现,部分结果被截断,显示为乱码。经查,发现是指针压缩问题,当内存小于32G的时候不存在问题,而大约32G的时候存在问题,由于我们设置的driver内存为40G超过了32G,所以该问题凸显,网上其他用户反馈,executor同样面临这个问题。
临时解决办法,添加下面两个配置:

-conf "spark.executor.extraJavaOptions=-XX:-UseCompressedOops" --driver-java-options "-XX:-UseCompressedOops" 

3.thriftserver内存泄露问题(https://issues.apache.org/jira/browse/SPARK-14261

影响版本:1.6.0
修复版本:1.6.2, 2.0.0
经查,该问题由HiveConf无法进行内存释放导致,随着SQL任务提交越来越小,真正可用内存会越来越少,导致thriftserver无法有效响应任务直至死亡。目前没有有效解决办法,只有升级到Spark1.6.2,经过目前的实践,建议使用该版本。

4.Spark2.x的CATS问题(参考我的原来的博客:http://blog.csdn.net/bon_mot/article/details/75256525

影响版本:2.1.1, 2.2.0
修复版本:None

我们知道在使用SparkSQL通过查询创建表是最常使用的场景,但是这个功能存在致命bug,目前还没有修复,建议不要轻易尝试使用。

5.使用密码验证

参考这篇文章:https://ieevee.com/tech/2016/05/18/spark-9-sts-auth.html
启动的时候加上这个参数就可以了。

--jars $SPARK_HOME/lib/sparkAuth.jar

6.GC问题

SparkSQL有时候会出现GC问题,这个时候可以适当考虑减少RDD缓存,降低spark.storage.memoryFraction的比例。但最重要的其实是解决SQL写法的问题,注意做好预处理再进行关联,避免重复扫描一些数据,也避免扫描不真正使用的数据。

7.group by与文件数目过多的导致的full GC

当文件数目特别多,且关联的对象文件数目也很多的时候,这个时候做聚合分析,很容易出现严重的GC问题。做法是分步骤实现,关联小表的文件数目不要太多,主表先做预处理,加上distribute by rand() 把文件数目先降下来。例子如下:

create table test_temp_20170912001 as
select t1.*, t2.*
  from test1 t1
 inner join test2 t2
    on t1.id = yt.id
   and t2.site in ('site1','site2','site3','site4')
 where t1.acct_month in (201706, 201707201708)
distribute by rand();

该例子上原本test1每个月文件数目默认是600个,三个月就是1800个,再关联test2,文件数目可达数千个。而使用了distribute by rand(),文件数目会变成默认的200个。原本可能无法跑过去的任务,可能几十秒就搞定了。

8.临时表关联写到where条件中

有的时候使用临时表再去做关联,不如直接写到where条件中,因为这个相当于对变量做了广播,性能会大幅度提升。

9.增加广播变量

可以增加广播变量参数,设置广播变量阈值。这个可以配置参数如下:

--conf spark.broadcast.compress=true \
--conf spark.sql.autoBroadcastJoinThreshold=104857600 \

但是这个奇怪的是,好像没有生效,可能是小表过大,超过了100M,分析解决中。

10.Parquet存储压缩(待解决)

通过使用Parquet存储,性能能够得到一定程度的提升,但是Parquet产生的结果目前来说压缩存在的一定的问题,insert数据无法使用snappy压缩,解决中。
设置下面的参数,sparkSQL不真正使用下面的参数:

TBLPROPERTIES (
  'Compressed'='true', 
  'parquet.compression'='SNAPPY'

已经测试过,可以排除这个问题。

11.KyroSerializer

序列化的时候需要加上下面的参数,避免出现buffer空间不足溢出的情况。

--conf spark.kryoserializer.buffer.max=256m  \
--conf spark.kryoserializer.buffer=64m \

12.使用hive表问题

有时候使用hive生成的中间表会导致程序不能正常响应,会报错,可能是catalyst语法解析上出现了问题。暂时没有找到具体原因,出问题了可以从这个思路排查一下。具体错误可能如下:

task error:java.sql.SQLException: org.apache.spark.sql.catalyst.errors.package$TreeNodeException: execute, tree:

13.动态资源分配

可以使用spark自身的动态资源分配参数,参考http://lxw1234.com/archives/2015/12/593.htm
以yarn-client模式启动ThriftServer:

cd $SPARK_HOME/sbin/
./start-thriftserver.sh \
--master yarn-client \
--conf spark.driver.memory=3G \
--conf spark.shuffle.service.enabled=true \
--conf spark.dynamicAllocation.enabled=true \
--conf spark.dynamicAllocation.minExecutors=1 \
--conf spark.dynamicAllocation.maxExecutors=30 \
--conf spark.dynamicAllocation.sustainedSchedulerBacklogTimeout=5s

启动后,ThriftServer会在Yarn上作为一个长服务来运行。

14.部分场合使用left semi join代替inner join

left semi join会自动进行广播变量,性能会大幅度提升,在某些场景下替代inner join,性能会有质的飞跃,值得尝试。它的产生动机是:对于reduce side join,跨机器的数据传输量非常大,这成了join操作的一个瓶颈,如果能够在map端过滤掉不会参加join操作的数据,则可以大大节省网络IO,提升执行效率。
但是要注意left semi join和inner join还是有区别的,一定要搞清楚这一块:

  • left semi join 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT
    子句或其他地方过滤都不行。
  • 对待右表中重复key的处理方式差异:因为 left semi join 是 in(keySet)的关系,遇到右表重复记录,左表会跳过,而join on 则会一直遍历。

参考文档

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值